diff options
Diffstat (limited to 'include/lldb/Breakpoint')
21 files changed, 3656 insertions, 3847 deletions
diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h index 7fdf06da3936..9af6e586de39 100644 --- a/include/lldb/Breakpoint/Breakpoint.h +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -20,13 +20,14 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointID.h" +#include "lldb/Breakpoint/BreakpointLocationCollection.h" #include "lldb/Breakpoint/BreakpointLocationList.h" #include "lldb/Breakpoint/BreakpointOptions.h" -#include "lldb/Breakpoint/BreakpointLocationCollection.h" #include "lldb/Breakpoint/Stoppoint.h" -#include "lldb/Core/SearchFilter.h" #include "lldb/Core/Event.h" +#include "lldb/Core/SearchFilter.h" #include "lldb/Core/StringList.h" +#include "lldb/Core/StructuredData.h" namespace lldb_private { @@ -37,27 +38,35 @@ namespace lldb_private { //---------------------------------------------------------------------- /// General Outline: -/// A breakpoint has four main parts, a filter, a resolver, the list of breakpoint -/// locations that have been determined for the filter/resolver pair, and finally +/// A breakpoint has four main parts, a filter, a resolver, the list of +/// breakpoint +/// locations that have been determined for the filter/resolver pair, and +/// finally /// a set of options for the breakpoint. /// /// \b Filter: /// This is an object derived from SearchFilter. It manages the search -/// for breakpoint location matches through the symbols in the module list of the target -/// that owns it. It also filters out locations based on whatever logic it wants. +/// for breakpoint location matches through the symbols in the module list of +/// the target +/// that owns it. It also filters out locations based on whatever logic it +/// wants. /// /// \b Resolver: /// This is an object derived from BreakpointResolver. It provides a -/// callback to the filter that will find breakpoint locations. How it does this is +/// callback to the filter that will find breakpoint locations. How it does +/// this is /// determined by what kind of resolver it is. /// -/// The Breakpoint class also provides constructors for the common breakpoint cases +/// The Breakpoint class also provides constructors for the common breakpoint +/// cases /// which make the appropriate filter and resolver for you. /// /// \b Location List: /// This stores the breakpoint locations that have been determined -/// to date. For a given breakpoint, there will be only one location with a given -/// address. Adding a location at an already taken address will just return the location +/// to date. For a given breakpoint, there will be only one location with a +/// given +/// address. Adding a location at an already taken address will just return the +/// location /// already at that address. Locations can be looked up by ID, or by address. /// /// \b Options: @@ -66,734 +75,687 @@ namespace lldb_private { /// \b Ignore Count /// \b Callback /// \b Condition -/// Note, these options can be set on the breakpoint, and they can also be set on the -/// individual locations. The options set on the breakpoint take precedence over the +/// Note, these options can be set on the breakpoint, and they can also be set +/// on the +/// individual locations. The options set on the breakpoint take precedence +/// over the /// options set on the individual location. -/// So for instance disabling the breakpoint will cause NONE of the locations to get hit. -/// But if the breakpoint is enabled, then the location's enabled state will be checked +/// So for instance disabling the breakpoint will cause NONE of the locations to +/// get hit. +/// But if the breakpoint is enabled, then the location's enabled state will be +/// checked /// to determine whether to insert that breakpoint location. -/// Similarly, if the breakpoint condition says "stop", we won't check the location's condition. -/// But if the breakpoint condition says "continue", then we will check the location for whether +/// Similarly, if the breakpoint condition says "stop", we won't check the +/// location's condition. +/// But if the breakpoint condition says "continue", then we will check the +/// location for whether /// to actually stop or not. -/// One subtle point worth observing here is that you don't actually stop at a Breakpoint, you -/// always stop at one of its locations. So the "should stop" tests are done by the location, +/// One subtle point worth observing here is that you don't actually stop at a +/// Breakpoint, you +/// always stop at one of its locations. So the "should stop" tests are done by +/// the location, /// not by the breakpoint. //---------------------------------------------------------------------- -class Breakpoint: - public std::enable_shared_from_this<Breakpoint>, - public Stoppoint -{ +class Breakpoint : public std::enable_shared_from_this<Breakpoint>, + public Stoppoint { public: - static const ConstString & - GetEventIdentifier (); - - //------------------------------------------------------------------ - /// An enum specifying the match style for breakpoint settings. At - /// present only used for function name style breakpoints. - //------------------------------------------------------------------ - typedef enum - { - Exact, - Regexp, - Glob - } MatchType; - - class BreakpointEventData : - public EventData - { - public: - BreakpointEventData (lldb::BreakpointEventType sub_type, - const lldb::BreakpointSP &new_breakpoint_sp); - - ~BreakpointEventData() override; - - static const ConstString & - GetFlavorString (); - - const ConstString & - GetFlavor() const override; - - lldb::BreakpointEventType - GetBreakpointEventType () const; - - lldb::BreakpointSP & - GetBreakpoint (); - - BreakpointLocationCollection & - GetBreakpointLocationCollection() - { - return m_locations; - } - - void - Dump(Stream *s) const override; - - static lldb::BreakpointEventType - GetBreakpointEventTypeFromEvent (const lldb::EventSP &event_sp); - - static lldb::BreakpointSP - GetBreakpointFromEvent (const lldb::EventSP &event_sp); - - static lldb::BreakpointLocationSP - GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t loc_idx); - - static size_t - GetNumBreakpointLocationsFromEvent (const lldb::EventSP &event_sp); - - static const BreakpointEventData * - GetEventDataFromEvent (const Event *event_sp); - - private: - lldb::BreakpointEventType m_breakpoint_event; - lldb::BreakpointSP m_new_breakpoint_sp; - BreakpointLocationCollection m_locations; - - DISALLOW_COPY_AND_ASSIGN (BreakpointEventData); - }; - - class BreakpointPrecondition - { - public: - virtual ~BreakpointPrecondition() = default; - - virtual bool - EvaluatePrecondition(StoppointCallbackContext &context); - - virtual Error - ConfigurePrecondition(Args &options); - - virtual void - GetDescription(Stream &stream, lldb::DescriptionLevel level); - }; - - typedef std::shared_ptr<BreakpointPrecondition> BreakpointPreconditionSP; - - //------------------------------------------------------------------ - /// Destructor. - /// - /// The destructor is not virtual since there should be no reason to subclass - /// breakpoints. The varieties of breakpoints are specified instead by - /// providing different resolvers & filters. - //------------------------------------------------------------------ - ~Breakpoint() override; - - //------------------------------------------------------------------ - // Methods - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Tell whether this breakpoint is an "internal" breakpoint. - /// @return - /// Returns \b true if this is an internal breakpoint, \b false otherwise. - //------------------------------------------------------------------ - bool - IsInternal () const; - - //------------------------------------------------------------------ - /// Standard "Dump" method. At present it does nothing. - //------------------------------------------------------------------ - void - Dump(Stream *s) override; - - //------------------------------------------------------------------ - // The next set of methods provide ways to tell the breakpoint to update - // it's location list - usually done when modules appear or disappear. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Tell this breakpoint to clear all its breakpoint sites. Done - /// when the process holding the breakpoint sites is destroyed. - //------------------------------------------------------------------ - void - ClearAllBreakpointSites (); - - //------------------------------------------------------------------ - /// Tell this breakpoint to scan it's target's module list and resolve any - /// new locations that match the breakpoint's specifications. - //------------------------------------------------------------------ - void - ResolveBreakpoint (); - - //------------------------------------------------------------------ - /// Tell this breakpoint to scan a given module list and resolve any - /// new locations that match the breakpoint's specifications. - /// - /// @param[in] module_list - /// The list of modules to look in for new locations. - /// - /// @param[in] send_event - /// If \b true, send a breakpoint location added event for non-internal breakpoints. - //------------------------------------------------------------------ - void - ResolveBreakpointInModules (ModuleList &module_list, bool send_event = true); - - //------------------------------------------------------------------ - /// Tell this breakpoint to scan a given module list and resolve any - /// new locations that match the breakpoint's specifications. - /// - /// @param[in] changed_modules - /// The list of modules to look in for new locations. - /// - /// @param[in] new_locations - /// Fills new_locations with the new locations that were made. - //------------------------------------------------------------------ - void - ResolveBreakpointInModules (ModuleList &module_list, BreakpointLocationCollection &new_locations); - - //------------------------------------------------------------------ - /// Like ResolveBreakpointInModules, but allows for "unload" events, in - /// which case we will remove any locations that are in modules that got - /// unloaded. - /// - /// @param[in] changedModules - /// The list of modules to look in for new locations. - /// @param[in] load_event - /// If \b true then the modules were loaded, if \b false, unloaded. - /// @param[in] delete_locations - /// If \b true then the modules were unloaded delete any locations in the changed modules. - //------------------------------------------------------------------ - void - ModulesChanged (ModuleList &changed_modules, - bool load_event, - bool delete_locations = false); - - //------------------------------------------------------------------ - /// Tells the breakpoint the old module \a old_module_sp has been - /// replaced by new_module_sp (usually because the underlying file has been - /// rebuilt, and the old version is gone.) - /// - /// @param[in] old_module_sp - /// The old module that is going away. - /// @param[in] new_module_sp - /// The new module that is replacing it. - //------------------------------------------------------------------ - void - ModuleReplaced (lldb::ModuleSP old_module_sp, lldb::ModuleSP new_module_sp); - - //------------------------------------------------------------------ - // The next set of methods provide access to the breakpoint locations - // for this breakpoint. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Add a location to the breakpoint's location list. This is only meant - /// to be called by the breakpoint's resolver. FIXME: how do I ensure that? - /// - /// @param[in] addr - /// The Address specifying the new location. - /// @param[out] new_location - /// Set to \b true if a new location was created, to \b false if there - /// already was a location at this Address. - /// @return - /// Returns a pointer to the new location. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - AddLocation(const Address &addr, - bool *new_location = nullptr); - - //------------------------------------------------------------------ - /// Find a breakpoint location by Address. - /// - /// @param[in] addr - /// The Address specifying the location. - /// @return - /// Returns a shared pointer to the location at \a addr. The pointer - /// in the shared pointer will be nullptr if there is no location at that address. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - FindLocationByAddress (const Address &addr); - - //------------------------------------------------------------------ - /// Find a breakpoint location ID by Address. - /// - /// @param[in] addr - /// The Address specifying the location. - /// @return - /// Returns the UID of the location at \a addr, or \b LLDB_INVALID_ID if - /// there is no breakpoint location at that address. - //------------------------------------------------------------------ - lldb::break_id_t - FindLocationIDByAddress (const Address &addr); - - //------------------------------------------------------------------ - /// Find a breakpoint location for a given breakpoint location ID. - /// - /// @param[in] bp_loc_id - /// The ID specifying the location. - /// @return - /// Returns a shared pointer to the location with ID \a bp_loc_id. The pointer - /// in the shared pointer will be nullptr if there is no location with that ID. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - FindLocationByID (lldb::break_id_t bp_loc_id); - - //------------------------------------------------------------------ - /// Get breakpoint locations by index. - /// - /// @param[in] index - /// The location index. - /// - /// @return - /// Returns a shared pointer to the location with index \a - /// index. The shared pointer might contain nullptr if \a index is - /// greater than then number of actual locations. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - GetLocationAtIndex (size_t index); - - //------------------------------------------------------------------ - /// Removes all invalid breakpoint locations. - /// - /// Removes all breakpoint locations with architectures that aren't - /// compatible with \a arch. Also remove any breakpoint locations - /// with whose locations have address where the section has been - /// deleted (module and object files no longer exist). - /// - /// This is typically used after the process calls exec, or anytime - /// the architecture of the target changes. - /// - /// @param[in] arch - /// If valid, check the module in each breakpoint to make sure - /// they are compatible, otherwise, ignore architecture. - //------------------------------------------------------------------ - void - RemoveInvalidLocations (const ArchSpec &arch); - - //------------------------------------------------------------------ - // The next section deals with various breakpoint options. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// If \a enable is \b true, enable the breakpoint, if \b false disable it. - //------------------------------------------------------------------ - void - SetEnabled(bool enable) override; - - //------------------------------------------------------------------ - /// Check the Enable/Disable state. - /// @return - /// \b true if the breakpoint is enabled, \b false if disabled. - //------------------------------------------------------------------ - bool - IsEnabled() override; - - //------------------------------------------------------------------ - /// Set the breakpoint to ignore the next \a count breakpoint hits. - /// @param[in] count - /// The number of breakpoint hits to ignore. - //------------------------------------------------------------------ - void - SetIgnoreCount (uint32_t count); - - //------------------------------------------------------------------ - /// Return the current ignore count/ - /// @return - /// The number of breakpoint hits to be ignored. - //------------------------------------------------------------------ - uint32_t - GetIgnoreCount () const; - - //------------------------------------------------------------------ - /// Return the current hit count for all locations. - /// @return - /// The current hit count for all locations. - //------------------------------------------------------------------ - uint32_t - GetHitCount () const; - - //------------------------------------------------------------------ - /// If \a one_shot is \b true, breakpoint will be deleted on first hit. - //------------------------------------------------------------------ - void - SetOneShot (bool one_shot); - - //------------------------------------------------------------------ - /// Check the OneShot state. - /// @return - /// \b true if the breakpoint is one shot, \b false otherwise. - //------------------------------------------------------------------ - bool - IsOneShot () const; - - //------------------------------------------------------------------ - /// Set the valid thread to be checked when the breakpoint is hit. - /// @param[in] thread_id - /// If this thread hits the breakpoint, we stop, otherwise not. - //------------------------------------------------------------------ - void - SetThreadID (lldb::tid_t thread_id); - - //------------------------------------------------------------------ - /// Return the current stop thread value. - /// @return - /// The thread id for which the breakpoint hit will stop, LLDB_INVALID_THREAD_ID for all threads. - //------------------------------------------------------------------ - lldb::tid_t - GetThreadID () const; - - void - SetThreadIndex (uint32_t index); - - uint32_t - GetThreadIndex() const; - - void - SetThreadName (const char *thread_name); - - const char * - GetThreadName () const; - - void - SetQueueName (const char *queue_name); - - const char * - GetQueueName () const; - - //------------------------------------------------------------------ - /// Set the callback action invoked when the breakpoint is hit. - /// - /// @param[in] callback - /// The method that will get called when the breakpoint is hit. - /// @param[in] baton - /// A void * pointer that will get passed back to the callback function. - /// @param[in] is_synchronous - /// If \b true the callback will be run on the private event thread - /// before the stop event gets reported. If false, the callback will get - /// handled on the public event thread after the stop has been posted. - /// - /// @return - /// \b true if the process should stop when you hit the breakpoint. - /// \b false if it should continue. - //------------------------------------------------------------------ - void - SetCallback (BreakpointHitCallback callback, - void *baton, - bool is_synchronous = false); - - void - SetCallback (BreakpointHitCallback callback, - const lldb::BatonSP &callback_baton_sp, - bool is_synchronous = false); - - void - ClearCallback (); - - //------------------------------------------------------------------ - /// Set the breakpoint's condition. - /// - /// @param[in] condition - /// The condition expression to evaluate when the breakpoint is hit. - /// Pass in nullptr to clear the condition. - //------------------------------------------------------------------ - void SetCondition (const char *condition); - - //------------------------------------------------------------------ - /// Return a pointer to the text of the condition expression. - /// - /// @return - /// A pointer to the condition expression text, or nullptr if no - // condition has been set. - //------------------------------------------------------------------ - const char *GetConditionText () const; - - //------------------------------------------------------------------ - // The next section are various utility functions. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Return the number of breakpoint locations that have resolved to - /// actual breakpoint sites. - /// - /// @return - /// The number locations resolved breakpoint sites. - //------------------------------------------------------------------ - size_t - GetNumResolvedLocations() const; - - //------------------------------------------------------------------ - /// Return the number of breakpoint locations. - /// - /// @return - /// The number breakpoint locations. - //------------------------------------------------------------------ - size_t - GetNumLocations() const; - - //------------------------------------------------------------------ - /// Put a description of this breakpoint into the stream \a s. - /// - /// @param[in] s - /// Stream into which to dump the description. - /// - /// @param[in] level - /// The description level that indicates the detail level to - /// provide. - /// - /// @see lldb::DescriptionLevel - //------------------------------------------------------------------ - void - GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations = false); - - //------------------------------------------------------------------ - /// Set the "kind" description for a breakpoint. If the breakpoint is hit - /// the stop info will show this "kind" description instead of the breakpoint - /// number. Mostly useful for internal breakpoints, where the breakpoint number - /// doesn't have meaning to the user. - /// - /// @param[in] kind - /// New "kind" description. - //------------------------------------------------------------------ - void - SetBreakpointKind (const char *kind) - { - m_kind_description.assign (kind); - } - - //------------------------------------------------------------------ - /// Return the "kind" description for a breakpoint. - /// - /// @return - /// The breakpoint kind, or nullptr if none is set. - //------------------------------------------------------------------ - const char *GetBreakpointKind () const - { - return m_kind_description.c_str(); - } + static const ConstString &GetEventIdentifier(); - //------------------------------------------------------------------ - /// Accessor for the breakpoint Target. - /// @return - /// This breakpoint's Target. - //------------------------------------------------------------------ - Target & - GetTarget () - { - return m_target; - } + //------------------------------------------------------------------ + /// An enum specifying the match style for breakpoint settings. At + /// present only used for function name style breakpoints. + //------------------------------------------------------------------ + typedef enum { Exact, Regexp, Glob } MatchType; - const Target & - GetTarget () const - { - return m_target; - } +private: + enum class OptionNames : uint32_t { Names = 0, Hardware, LastOptionName }; - const lldb::TargetSP - GetTargetSP (); - - void - GetResolverDescription (Stream *s); - - //------------------------------------------------------------------ - /// Find breakpoint locations which match the (filename, line_number) description. - /// The breakpoint location collection is to be filled with the matching locations. - /// It should be initialized with 0 size by the API client. - /// - /// @return - /// True if there is a match - /// - /// The locations which match the filename and line_number in loc_coll. If its - /// size is 0 and true is returned, it means the breakpoint fully matches the - /// description. - //------------------------------------------------------------------ - bool GetMatchingFileLine(const ConstString &filename, uint32_t line_number, - BreakpointLocationCollection &loc_coll); - - void - GetFilterDescription (Stream *s); - - //------------------------------------------------------------------ - /// Returns the BreakpointOptions structure set at the breakpoint level. - /// - /// Meant to be used by the BreakpointLocation class. - /// - /// @return - /// A pointer to this breakpoint's BreakpointOptions. - //------------------------------------------------------------------ - BreakpointOptions * - GetOptions (); - - //------------------------------------------------------------------ - /// Invoke the callback action when the breakpoint is hit. - /// - /// Meant to be used by the BreakpointLocation class. - /// - /// @param[in] context - /// Described the breakpoint event. - /// - /// @param[in] bp_loc_id - /// Which breakpoint location hit this breakpoint. - /// - /// @return - /// \b true if the target should stop at this breakpoint and \b false not. - //------------------------------------------------------------------ - bool - InvokeCallback (StoppointCallbackContext *context, - lldb::break_id_t bp_loc_id); - - bool - IsHardware() const - { - return m_hardware; - } + static const char + *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)]; - lldb::BreakpointResolverSP - GetResolver() - { - return m_resolver_sp; - } + static const char *GetKey(OptionNames enum_value) { + return g_option_names[static_cast<uint32_t>(enum_value)]; + } - lldb::SearchFilterSP - GetSearchFilter() - { - return m_filter_sp; - } +public: + class BreakpointEventData : public EventData { + public: + BreakpointEventData(lldb::BreakpointEventType sub_type, + const lldb::BreakpointSP &new_breakpoint_sp); - bool - AddName (const char *new_name, Error &error); + ~BreakpointEventData() override; - void - RemoveName (const char *name_to_remove) - { - if (name_to_remove) - m_name_list.erase(name_to_remove); - } - - bool - MatchesName (const char *name) - { - return m_name_list.find(name) != m_name_list.end(); - } + static const ConstString &GetFlavorString(); - void - GetNames (std::vector<std::string> &names) - { - names.clear(); - for (auto name : m_name_list) - { - names.push_back(name); - } - } + const ConstString &GetFlavor() const override; - //------------------------------------------------------------------ - /// 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; - } + lldb::BreakpointEventType GetBreakpointEventType() const; - bool - EvaluatePrecondition (StoppointCallbackContext &context); + lldb::BreakpointSP &GetBreakpoint(); - BreakpointPreconditionSP - GetPrecondition() - { - return m_precondition_sp; + BreakpointLocationCollection &GetBreakpointLocationCollection() { + return m_locations; } -protected: - friend class Target; - //------------------------------------------------------------------ - // Protected Methods - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Constructors and Destructors - /// Only the Target can make a breakpoint, and it owns the breakpoint lifespans. - /// The constructor takes a filter and a resolver. Up in Target there are convenience - /// variants that make breakpoints for some common cases. - /// - /// @param[in] target - /// The target in which the breakpoint will be set. - /// - /// @param[in] filter_sp - /// Shared pointer to the search filter that restricts the search domain of the breakpoint. - /// - /// @param[in] resolver_sp - /// Shared pointer to the resolver object that will determine breakpoint matches. - /// - /// @param hardware - /// If true, request a hardware breakpoint to be used to implement the breakpoint locations. - /// - /// @param resolve_indirect_symbols - /// If true, and the address of a given breakpoint location in this breakpoint is set on an - /// indirect symbol (i.e. Symbol::IsIndirect returns true) then the actual breakpoint site will - /// be set on the target of the indirect symbol. - //------------------------------------------------------------------ - // This is the generic constructor - Breakpoint(Target &target, - lldb::SearchFilterSP &filter_sp, - lldb::BreakpointResolverSP &resolver_sp, - bool hardware, - bool resolve_indirect_symbols = true); - - friend class BreakpointLocation; // To call the following two when determining whether to stop. - - void - DecrementIgnoreCount(); - - // BreakpointLocation::IgnoreCountShouldStop & Breakpoint::IgnoreCountShouldStop can only be called once per stop, - // and BreakpointLocation::IgnoreCountShouldStop should be tested first, and if it returns false we should - // continue, otherwise we should test Breakpoint::IgnoreCountShouldStop. - - bool - IgnoreCountShouldStop (); - - void - IncrementHitCount() - { - m_hit_count++; + void Dump(Stream *s) const override; + + static lldb::BreakpointEventType + GetBreakpointEventTypeFromEvent(const lldb::EventSP &event_sp); + + static lldb::BreakpointSP + GetBreakpointFromEvent(const lldb::EventSP &event_sp); + + static lldb::BreakpointLocationSP + GetBreakpointLocationAtIndexFromEvent(const lldb::EventSP &event_sp, + uint32_t loc_idx); + + static size_t + GetNumBreakpointLocationsFromEvent(const lldb::EventSP &event_sp); + + static const BreakpointEventData * + GetEventDataFromEvent(const Event *event_sp); + + private: + lldb::BreakpointEventType m_breakpoint_event; + lldb::BreakpointSP m_new_breakpoint_sp; + BreakpointLocationCollection m_locations; + + DISALLOW_COPY_AND_ASSIGN(BreakpointEventData); + }; + + class BreakpointPrecondition { + public: + virtual ~BreakpointPrecondition() = default; + + virtual bool EvaluatePrecondition(StoppointCallbackContext &context); + + virtual Error ConfigurePrecondition(Args &options); + + virtual void GetDescription(Stream &stream, lldb::DescriptionLevel level); + }; + + typedef std::shared_ptr<BreakpointPrecondition> BreakpointPreconditionSP; + + // Saving & restoring breakpoints: + static lldb::BreakpointSP CreateFromStructuredData( + Target &target, StructuredData::ObjectSP &data_object_sp, Error &error); + + static bool + SerializedBreakpointMatchesNames(StructuredData::ObjectSP &bkpt_object_sp, + std::vector<std::string> &names); + + virtual StructuredData::ObjectSP SerializeToStructuredData(); + + static const char *GetSerializationKey() { return "Breakpoint"; } + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is not virtual since there should be no reason to subclass + /// breakpoints. The varieties of breakpoints are specified instead by + /// providing different resolvers & filters. + //------------------------------------------------------------------ + ~Breakpoint() override; + + //------------------------------------------------------------------ + // Methods + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Tell whether this breakpoint is an "internal" breakpoint. + /// @return + /// Returns \b true if this is an internal breakpoint, \b false otherwise. + //------------------------------------------------------------------ + bool IsInternal() const; + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void Dump(Stream *s) override; + + //------------------------------------------------------------------ + // The next set of methods provide ways to tell the breakpoint to update + // it's location list - usually done when modules appear or disappear. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Tell this breakpoint to clear all its breakpoint sites. Done + /// when the process holding the breakpoint sites is destroyed. + //------------------------------------------------------------------ + void ClearAllBreakpointSites(); + + //------------------------------------------------------------------ + /// Tell this breakpoint to scan it's target's module list and resolve any + /// new locations that match the breakpoint's specifications. + //------------------------------------------------------------------ + void ResolveBreakpoint(); + + //------------------------------------------------------------------ + /// Tell this breakpoint to scan a given module list and resolve any + /// new locations that match the breakpoint's specifications. + /// + /// @param[in] module_list + /// The list of modules to look in for new locations. + /// + /// @param[in] send_event + /// If \b true, send a breakpoint location added event for non-internal + /// breakpoints. + //------------------------------------------------------------------ + void ResolveBreakpointInModules(ModuleList &module_list, + bool send_event = true); + + //------------------------------------------------------------------ + /// Tell this breakpoint to scan a given module list and resolve any + /// new locations that match the breakpoint's specifications. + /// + /// @param[in] changed_modules + /// The list of modules to look in for new locations. + /// + /// @param[in] new_locations + /// Fills new_locations with the new locations that were made. + //------------------------------------------------------------------ + void ResolveBreakpointInModules(ModuleList &module_list, + BreakpointLocationCollection &new_locations); + + //------------------------------------------------------------------ + /// Like ResolveBreakpointInModules, but allows for "unload" events, in + /// which case we will remove any locations that are in modules that got + /// unloaded. + /// + /// @param[in] changedModules + /// The list of modules to look in for new locations. + /// @param[in] load_event + /// If \b true then the modules were loaded, if \b false, unloaded. + /// @param[in] delete_locations + /// If \b true then the modules were unloaded delete any locations in the + /// changed modules. + //------------------------------------------------------------------ + void ModulesChanged(ModuleList &changed_modules, bool load_event, + bool delete_locations = false); + + //------------------------------------------------------------------ + /// Tells the breakpoint the old module \a old_module_sp has been + /// replaced by new_module_sp (usually because the underlying file has been + /// rebuilt, and the old version is gone.) + /// + /// @param[in] old_module_sp + /// The old module that is going away. + /// @param[in] new_module_sp + /// The new module that is replacing it. + //------------------------------------------------------------------ + void ModuleReplaced(lldb::ModuleSP old_module_sp, + lldb::ModuleSP new_module_sp); + + //------------------------------------------------------------------ + // The next set of methods provide access to the breakpoint locations + // for this breakpoint. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Add a location to the breakpoint's location list. This is only meant + /// to be called by the breakpoint's resolver. FIXME: how do I ensure that? + /// + /// @param[in] addr + /// The Address specifying the new location. + /// @param[out] new_location + /// Set to \b true if a new location was created, to \b false if there + /// already was a location at this Address. + /// @return + /// Returns a pointer to the new location. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP AddLocation(const Address &addr, + bool *new_location = nullptr); + + //------------------------------------------------------------------ + /// Find a breakpoint location by Address. + /// + /// @param[in] addr + /// The Address specifying the location. + /// @return + /// Returns a shared pointer to the location at \a addr. The pointer + /// in the shared pointer will be nullptr if there is no location at that + /// address. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP FindLocationByAddress(const Address &addr); + + //------------------------------------------------------------------ + /// Find a breakpoint location ID by Address. + /// + /// @param[in] addr + /// The Address specifying the location. + /// @return + /// Returns the UID of the location at \a addr, or \b LLDB_INVALID_ID if + /// there is no breakpoint location at that address. + //------------------------------------------------------------------ + lldb::break_id_t FindLocationIDByAddress(const Address &addr); + + //------------------------------------------------------------------ + /// Find a breakpoint location for a given breakpoint location ID. + /// + /// @param[in] bp_loc_id + /// The ID specifying the location. + /// @return + /// Returns a shared pointer to the location with ID \a bp_loc_id. The + /// pointer + /// in the shared pointer will be nullptr if there is no location with that + /// ID. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP FindLocationByID(lldb::break_id_t bp_loc_id); + + //------------------------------------------------------------------ + /// Get breakpoint locations by index. + /// + /// @param[in] index + /// The location index. + /// + /// @return + /// Returns a shared pointer to the location with index \a + /// index. The shared pointer might contain nullptr if \a index is + /// greater than then number of actual locations. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP GetLocationAtIndex(size_t index); + + //------------------------------------------------------------------ + /// Removes all invalid breakpoint locations. + /// + /// Removes all breakpoint locations with architectures that aren't + /// compatible with \a arch. Also remove any breakpoint locations + /// with whose locations have address where the section has been + /// deleted (module and object files no longer exist). + /// + /// This is typically used after the process calls exec, or anytime + /// the architecture of the target changes. + /// + /// @param[in] arch + /// If valid, check the module in each breakpoint to make sure + /// they are compatible, otherwise, ignore architecture. + //------------------------------------------------------------------ + void RemoveInvalidLocations(const ArchSpec &arch); + + //------------------------------------------------------------------ + // The next section deals with various breakpoint options. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false disable it. + //------------------------------------------------------------------ + void SetEnabled(bool enable) override; + + //------------------------------------------------------------------ + /// Check the Enable/Disable state. + /// @return + /// \b true if the breakpoint is enabled, \b false if disabled. + //------------------------------------------------------------------ + bool IsEnabled() override; + + //------------------------------------------------------------------ + /// Set the breakpoint to ignore the next \a count breakpoint hits. + /// @param[in] count + /// The number of breakpoint hits to ignore. + //------------------------------------------------------------------ + void SetIgnoreCount(uint32_t count); + + //------------------------------------------------------------------ + /// Return the current ignore count/ + /// @return + /// The number of breakpoint hits to be ignored. + //------------------------------------------------------------------ + uint32_t GetIgnoreCount() const; + + //------------------------------------------------------------------ + /// Return the current hit count for all locations. + /// @return + /// The current hit count for all locations. + //------------------------------------------------------------------ + uint32_t GetHitCount() const; + + //------------------------------------------------------------------ + /// If \a one_shot is \b true, breakpoint will be deleted on first hit. + //------------------------------------------------------------------ + void SetOneShot(bool one_shot); + + //------------------------------------------------------------------ + /// Check the OneShot state. + /// @return + /// \b true if the breakpoint is one shot, \b false otherwise. + //------------------------------------------------------------------ + bool IsOneShot() const; + + //------------------------------------------------------------------ + /// Set the valid thread to be checked when the breakpoint is hit. + /// @param[in] thread_id + /// If this thread hits the breakpoint, we stop, otherwise not. + //------------------------------------------------------------------ + void SetThreadID(lldb::tid_t thread_id); + + //------------------------------------------------------------------ + /// Return the current stop thread value. + /// @return + /// The thread id for which the breakpoint hit will stop, + /// LLDB_INVALID_THREAD_ID for all threads. + //------------------------------------------------------------------ + lldb::tid_t GetThreadID() const; + + void SetThreadIndex(uint32_t index); + + uint32_t GetThreadIndex() const; + + void SetThreadName(const char *thread_name); + + const char *GetThreadName() const; + + void SetQueueName(const char *queue_name); + + const char *GetQueueName() const; + + //------------------------------------------------------------------ + /// Set the callback action invoked when the breakpoint is hit. + /// + /// @param[in] callback + /// The method that will get called when the breakpoint is hit. + /// @param[in] baton + /// A void * pointer that will get passed back to the callback function. + /// @param[in] is_synchronous + /// If \b true the callback will be run on the private event thread + /// before the stop event gets reported. If false, the callback will get + /// handled on the public event thread after the stop has been posted. + /// + /// @return + /// \b true if the process should stop when you hit the breakpoint. + /// \b false if it should continue. + //------------------------------------------------------------------ + void SetCallback(BreakpointHitCallback callback, void *baton, + bool is_synchronous = false); + + void SetCallback(BreakpointHitCallback callback, + const lldb::BatonSP &callback_baton_sp, + bool is_synchronous = false); + + void ClearCallback(); + + //------------------------------------------------------------------ + /// Set the breakpoint's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the breakpoint is hit. + /// Pass in nullptr to clear the condition. + //------------------------------------------------------------------ + void SetCondition(const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or nullptr if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText() const; + + //------------------------------------------------------------------ + // The next section are various utility functions. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Return the number of breakpoint locations that have resolved to + /// actual breakpoint sites. + /// + /// @return + /// The number locations resolved breakpoint sites. + //------------------------------------------------------------------ + size_t GetNumResolvedLocations() const; + + //------------------------------------------------------------------ + /// Return the number of breakpoint locations. + /// + /// @return + /// The number breakpoint locations. + //------------------------------------------------------------------ + size_t GetNumLocations() const; + + //------------------------------------------------------------------ + /// Put a description of this breakpoint into the stream \a s. + /// + /// @param[in] s + /// Stream into which to dump the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription(Stream *s, lldb::DescriptionLevel level, + bool show_locations = false); + + //------------------------------------------------------------------ + /// Set the "kind" description for a breakpoint. If the breakpoint is hit + /// the stop info will show this "kind" description instead of the breakpoint + /// number. Mostly useful for internal breakpoints, where the breakpoint + /// number + /// doesn't have meaning to the user. + /// + /// @param[in] kind + /// New "kind" description. + //------------------------------------------------------------------ + void SetBreakpointKind(const char *kind) { m_kind_description.assign(kind); } + + //------------------------------------------------------------------ + /// Return the "kind" description for a breakpoint. + /// + /// @return + /// The breakpoint kind, or nullptr if none is set. + //------------------------------------------------------------------ + const char *GetBreakpointKind() const { return m_kind_description.c_str(); } + + //------------------------------------------------------------------ + /// Accessor for the breakpoint Target. + /// @return + /// This breakpoint's Target. + //------------------------------------------------------------------ + Target &GetTarget() { return m_target; } + + const Target &GetTarget() const { return m_target; } + + const lldb::TargetSP GetTargetSP(); + + void GetResolverDescription(Stream *s); + + //------------------------------------------------------------------ + /// Find breakpoint locations which match the (filename, line_number) + /// description. + /// The breakpoint location collection is to be filled with the matching + /// locations. + /// It should be initialized with 0 size by the API client. + /// + /// @return + /// True if there is a match + /// + /// The locations which match the filename and line_number in loc_coll. + /// If its + /// size is 0 and true is returned, it means the breakpoint fully matches + /// the + /// description. + //------------------------------------------------------------------ + bool GetMatchingFileLine(const ConstString &filename, uint32_t line_number, + BreakpointLocationCollection &loc_coll); + + void GetFilterDescription(Stream *s); + + //------------------------------------------------------------------ + /// Returns the BreakpointOptions structure set at the breakpoint level. + /// + /// Meant to be used by the BreakpointLocation class. + /// + /// @return + /// A pointer to this breakpoint's BreakpointOptions. + //------------------------------------------------------------------ + BreakpointOptions *GetOptions(); + + //------------------------------------------------------------------ + /// Invoke the callback action when the breakpoint is hit. + /// + /// Meant to be used by the BreakpointLocation class. + /// + /// @param[in] context + /// Described the breakpoint event. + /// + /// @param[in] bp_loc_id + /// Which breakpoint location hit this breakpoint. + /// + /// @return + /// \b true if the target should stop at this breakpoint and \b false not. + //------------------------------------------------------------------ + bool InvokeCallback(StoppointCallbackContext *context, + lldb::break_id_t bp_loc_id); + + bool IsHardware() const { return m_hardware; } + + lldb::BreakpointResolverSP GetResolver() { return m_resolver_sp; } + + lldb::SearchFilterSP GetSearchFilter() { return m_filter_sp; } + + bool AddName(const char *new_name, Error &error); + + void RemoveName(const char *name_to_remove) { + if (name_to_remove) + m_name_list.erase(name_to_remove); + } + + bool MatchesName(const char *name) { + return m_name_list.find(name) != m_name_list.end(); + } + + void GetNames(std::vector<std::string> &names) { + names.clear(); + for (auto name : m_name_list) { + names.push_back(name); } + } + + //------------------------------------------------------------------ + /// 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; } - void - DecrementHitCount() - { - assert (m_hit_count > 0); - m_hit_count--; - } +protected: + friend class Target; + //------------------------------------------------------------------ + // Protected Methods + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Constructors and Destructors + /// Only the Target can make a breakpoint, and it owns the breakpoint + /// lifespans. + /// The constructor takes a filter and a resolver. Up in Target there are + /// convenience + /// variants that make breakpoints for some common cases. + /// + /// @param[in] target + /// The target in which the breakpoint will be set. + /// + /// @param[in] filter_sp + /// Shared pointer to the search filter that restricts the search domain of + /// the breakpoint. + /// + /// @param[in] resolver_sp + /// Shared pointer to the resolver object that will determine breakpoint + /// matches. + /// + /// @param hardware + /// If true, request a hardware breakpoint to be used to implement the + /// breakpoint locations. + /// + /// @param resolve_indirect_symbols + /// If true, and the address of a given breakpoint location in this + /// breakpoint is set on an + /// indirect symbol (i.e. Symbol::IsIndirect returns true) then the actual + /// breakpoint site will + /// be set on the target of the indirect symbol. + //------------------------------------------------------------------ + // This is the generic constructor + Breakpoint(Target &target, lldb::SearchFilterSP &filter_sp, + lldb::BreakpointResolverSP &resolver_sp, bool hardware, + bool resolve_indirect_symbols = true); + + friend class BreakpointLocation; // To call the following two when determining + // whether to stop. + + void DecrementIgnoreCount(); + + // BreakpointLocation::IgnoreCountShouldStop & + // Breakpoint::IgnoreCountShouldStop can only be called once per stop, + // and BreakpointLocation::IgnoreCountShouldStop should be tested first, and + // if it returns false we should + // continue, otherwise we should test Breakpoint::IgnoreCountShouldStop. + + bool IgnoreCountShouldStop(); + + void IncrementHitCount() { m_hit_count++; } + + void DecrementHitCount() { + assert(m_hit_count > 0); + m_hit_count--; + } private: - // This one should only be used by Target to copy breakpoints from target to target - primarily from the dummy - // target to prime new targets. - Breakpoint (Target &new_target, - Breakpoint &bp_to_copy_from); - - //------------------------------------------------------------------ - // 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. - 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. - 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 - // separately from the locations hit counts, since locations can go away when - // their backing library gets unloaded, and we would lose hit counts. - - void - SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind); - - void - SendBreakpointChangedEvent (BreakpointEventData *data); - - DISALLOW_COPY_AND_ASSIGN(Breakpoint); + // This one should only be used by Target to copy breakpoints from target to + // target - primarily from the dummy + // target to prime new targets. + Breakpoint(Target &new_target, Breakpoint &bp_to_copy_from); + + //------------------------------------------------------------------ + // 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. + 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. + 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. + std::unique_ptr<BreakpointOptions> + m_options_up; // 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 + // separately from the locations hit counts, since locations can go away when + // their backing library gets unloaded, and we would lose hit counts. + + void SendBreakpointChangedEvent(lldb::BreakpointEventType eventKind); + + void SendBreakpointChangedEvent(BreakpointEventData *data); + + DISALLOW_COPY_AND_ASSIGN(Breakpoint); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointID.h b/include/lldb/Breakpoint/BreakpointID.h index 5ca09634ee09..aa4add4cd665 100644 --- a/include/lldb/Breakpoint/BreakpointID.h +++ b/include/lldb/Breakpoint/BreakpointID.h @@ -17,116 +17,95 @@ #include "lldb/lldb-private.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" + namespace lldb_private { //---------------------------------------------------------------------- // class BreakpointID //---------------------------------------------------------------------- -class BreakpointID -{ +class BreakpointID { public: - - BreakpointID (lldb::break_id_t bp_id = LLDB_INVALID_BREAK_ID, - lldb::break_id_t loc_id = LLDB_INVALID_BREAK_ID); - - virtual - ~BreakpointID (); - - lldb::break_id_t - GetBreakpointID () - { - return m_break_id; - } - - lldb::break_id_t - GetLocationID () - { - return m_location_id; - } - - void - SetID (lldb::break_id_t bp_id, lldb::break_id_t loc_id) - { - m_break_id = bp_id; - m_location_id = loc_id; - } - - void - SetBreakpointID (lldb::break_id_t bp_id) - { - m_break_id = bp_id; - } - - void - SetBreakpointLocationID (lldb::break_id_t loc_id) - { - m_location_id = loc_id; - } - - void - GetDescription (Stream *s, lldb::DescriptionLevel level); - - static bool - IsRangeIdentifier (const char *str); - - static bool - IsValidIDExpression (const char *str); - - static const char *g_range_specifiers[]; - - //------------------------------------------------------------------ - /// Takes an input string containing the description of a breakpoint or breakpoint and location - /// and returns the breakpoint ID and the breakpoint location id. - /// - /// @param[in] input - /// A string containing JUST the breakpoint description. - /// @param[out] break_id - /// This is the break id. - /// @param[out] break_loc_id - /// This is breakpoint location id, or LLDB_INVALID_BREAK_ID is no location was specified. - /// @return - /// \b true if the call was able to extract a breakpoint location from the string. \b false otherwise. - //------------------------------------------------------------------ - static bool - ParseCanonicalReference (const char *input, lldb::break_id_t *break_id, lldb::break_id_t *break_loc_id); - - - //------------------------------------------------------------------ - /// Takes an input string and checks to see whether it is a breakpoint name. - /// If it is a mal-formed breakpoint name, error will be set to an appropriate - /// error string. - /// - /// @param[in] input - /// A string containing JUST the breakpoint description. - /// @param[out] error - /// If the name is a well-formed breakpoint name, set to success, otherwise set to an error. - /// @return - /// \b true if the name is a breakpoint name (as opposed to an ID or range) false otherwise. - //------------------------------------------------------------------ - static bool - StringIsBreakpointName (const char *name, Error &error); - - //------------------------------------------------------------------ - /// Takes a breakpoint ID and the breakpoint location id and returns - /// a string containing the canonical description for the breakpoint - /// or breakpoint location. - /// - /// @param[out] break_id - /// This is the break id. - /// - /// @param[out] break_loc_id - /// This is breakpoint location id, or LLDB_INVALID_BREAK_ID is no - /// location is to be specified. - //------------------------------------------------------------------ - static void - GetCanonicalReference (Stream *s, lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + BreakpointID(lldb::break_id_t bp_id = LLDB_INVALID_BREAK_ID, + lldb::break_id_t loc_id = LLDB_INVALID_BREAK_ID); + + virtual ~BreakpointID(); + + lldb::break_id_t GetBreakpointID() const { return m_break_id; } + + lldb::break_id_t GetLocationID() const { return m_location_id; } + + void SetID(lldb::break_id_t bp_id, lldb::break_id_t loc_id) { + m_break_id = bp_id; + m_location_id = loc_id; + } + + void SetBreakpointID(lldb::break_id_t bp_id) { m_break_id = bp_id; } + + void SetBreakpointLocationID(lldb::break_id_t loc_id) { + m_location_id = loc_id; + } + + void GetDescription(Stream *s, lldb::DescriptionLevel level); + + static bool IsRangeIdentifier(llvm::StringRef str); + static bool IsValidIDExpression(llvm::StringRef str); + static llvm::ArrayRef<llvm::StringRef> GetRangeSpecifiers(); + + //------------------------------------------------------------------ + /// Takes an input string containing the description of a breakpoint or + /// breakpoint and location and returns the a BreakpointID filled out with + /// the proper id and location. + /// + /// @param[in] input + /// A string containing JUST the breakpoint description. + /// @return + /// If \p input was not a valid breakpoint ID string, returns + /// \b llvm::None. Otherwise returns a BreakpointID with members filled + /// out accordingly. + //------------------------------------------------------------------ + static llvm::Optional<BreakpointID> + ParseCanonicalReference(llvm::StringRef input); + + //------------------------------------------------------------------ + /// Takes an input string and checks to see whether it is a breakpoint name. + /// If it is a mal-formed breakpoint name, error will be set to an appropriate + /// error string. + /// + /// @param[in] input + /// A string containing JUST the breakpoint description. + /// @param[out] error + /// If the name is a well-formed breakpoint name, set to success, + /// otherwise set to an error. + /// @return + /// \b true if the name is a breakpoint name (as opposed to an ID or + /// range) false otherwise. + //------------------------------------------------------------------ + static bool StringIsBreakpointName(llvm::StringRef str, Error &error); + + //------------------------------------------------------------------ + /// Takes a breakpoint ID and the breakpoint location id and returns + /// a string containing the canonical description for the breakpoint + /// or breakpoint location. + /// + /// @param[out] break_id + /// This is the break id. + /// + /// @param[out] break_loc_id + /// This is breakpoint location id, or LLDB_INVALID_BREAK_ID is no + /// location is to be specified. + //------------------------------------------------------------------ + static void GetCanonicalReference(Stream *s, lldb::break_id_t break_id, + lldb::break_id_t break_loc_id); protected: - lldb::break_id_t m_break_id; - lldb::break_id_t m_location_id; + lldb::break_id_t m_break_id; + lldb::break_id_t m_location_id; }; } // namespace lldb_private -#endif // liblldb_BreakpointID_h_ +#endif // liblldb_BreakpointID_h_ diff --git a/include/lldb/Breakpoint/BreakpointIDList.h b/include/lldb/Breakpoint/BreakpointIDList.h index c42787066617..34cfbfe3268d 100644 --- a/include/lldb/Breakpoint/BreakpointIDList.h +++ b/include/lldb/Breakpoint/BreakpointIDList.h @@ -12,13 +12,14 @@ // C Includes // C++ Includes +#include <utility> #include <vector> // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Breakpoint/BreakpointID.h" +#include "lldb/lldb-private.h" namespace lldb_private { @@ -26,57 +27,53 @@ namespace lldb_private { // class BreakpointIDList //---------------------------------------------------------------------- - -class BreakpointIDList -{ +class BreakpointIDList { public: - typedef std::vector<BreakpointID> BreakpointIDArray; + // TODO: Convert this class to StringRef. + typedef std::vector<BreakpointID> BreakpointIDArray; - BreakpointIDList (); + BreakpointIDList(); - virtual - ~BreakpointIDList (); + virtual ~BreakpointIDList(); - size_t - GetSize(); + size_t GetSize() const; - BreakpointID & - GetBreakpointIDAtIndex (size_t index); + const BreakpointID &GetBreakpointIDAtIndex(size_t index) const; - bool - RemoveBreakpointIDAtIndex (size_t index); + bool RemoveBreakpointIDAtIndex(size_t index); - void - Clear(); + void Clear(); - bool - AddBreakpointID (BreakpointID bp_id); + bool AddBreakpointID(BreakpointID bp_id); - bool - AddBreakpointID (const char *bp_id); + bool AddBreakpointID(const char *bp_id); - bool - FindBreakpointID (BreakpointID &bp_id, size_t *position); + // TODO: This should take a const BreakpointID. + bool FindBreakpointID(BreakpointID &bp_id, size_t *position) const; - bool - FindBreakpointID (const char *bp_id, size_t *position); + bool FindBreakpointID(const char *bp_id, size_t *position) const; - void - InsertStringArray (const char **string_array, size_t array_size, CommandReturnObject &result); + void InsertStringArray(const char **string_array, size_t array_size, + CommandReturnObject &result); - static bool - StringContainsIDRangeExpression (const char *in_string, size_t *range_start_len, size_t *range_end_pos); + // Returns a pair consisting of the beginning and end of a breakpoint + // ID range expression. If the input string is not a valid specification, + // returns an empty pair. + static std::pair<llvm::StringRef, llvm::StringRef> + SplitIDRangeExpression(llvm::StringRef in_string); - static void - FindAndReplaceIDRanges (Args &old_args, Target *target, bool allow_locations, CommandReturnObject &result, Args &new_args); + static void FindAndReplaceIDRanges(Args &old_args, Target *target, + bool allow_locations, + CommandReturnObject &result, + Args &new_args); private: - BreakpointIDArray m_breakpoint_ids; - BreakpointID m_invalid_id; + BreakpointIDArray m_breakpoint_ids; + BreakpointID m_invalid_id; - DISALLOW_COPY_AND_ASSIGN(BreakpointIDList); + DISALLOW_COPY_AND_ASSIGN(BreakpointIDList); }; } // namespace lldb_private -#endif // liblldb_BreakpointIDList_h_ +#endif // liblldb_BreakpointIDList_h_ diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h index 5ddde7d837c4..2865288acc59 100644 --- a/include/lldb/Breakpoint/BreakpointList.h +++ b/include/lldb/Breakpoint/BreakpointList.h @@ -31,204 +31,192 @@ namespace lldb_private { /// Allows adding and removing breakpoints and find by ID and index. //---------------------------------------------------------------------- -class BreakpointList -{ +class BreakpointList { public: - BreakpointList (bool is_internal); - - ~BreakpointList(); - - //------------------------------------------------------------------ - /// Add the breakpoint \a bp_sp to the list. - /// - /// @param[in] bp_sp - /// Shared pointer to the breakpoint that will get added to the list. - /// - /// @result - /// Returns breakpoint id. - //------------------------------------------------------------------ - lldb::break_id_t - Add (lldb::BreakpointSP& bp_sp, bool notify); - - //------------------------------------------------------------------ - /// Standard "Dump" method. At present it does nothing. - //------------------------------------------------------------------ - void - Dump (Stream *s) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint with id \a breakID. - /// - /// @param[in] breakID - /// The breakpoint ID to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointSP - FindBreakpointByID (lldb::break_id_t breakID); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint with id \a breakID. Const version. - /// - /// @param[in] breakID - /// The breakpoint ID to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointSP - FindBreakpointByID (lldb::break_id_t breakID) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint with index \a i. - /// - /// @param[in] i - /// The breakpoint index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointSP - GetBreakpointAtIndex (size_t i); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint with index \a i, const version - /// - /// @param[in] i - /// The breakpoint index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointSP - GetBreakpointAtIndex (size_t i) const; - - //------------------------------------------------------------------ - /// Returns the number of elements in this breakpoint list. - /// - /// @result - /// The number of elements. - //------------------------------------------------------------------ - size_t - GetSize() const - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_breakpoints.size(); - } - - //------------------------------------------------------------------ - /// Removes the breakpoint given by \b breakID from this list. - /// - /// @param[in] breakID - /// The breakpoint index to remove. - /// - /// @result - /// \b true if the breakpoint \a breakID was in the list. - //------------------------------------------------------------------ - bool - Remove (lldb::break_id_t breakID, bool notify); - - - //------------------------------------------------------------------ - /// Removes all invalid breakpoint locations. - /// - /// Removes all breakpoint locations in the list with architectures - /// that aren't compatible with \a arch. Also remove any breakpoint - /// locations with whose locations have address where the section - /// has been deleted (module and object files no longer exist). - /// - /// This is typically used after the process calls exec, or anytime - /// the architecture of the target changes. - /// - /// @param[in] arch - /// If valid, check the module in each breakpoint to make sure - /// they are compatible, otherwise, ignore architecture. - //------------------------------------------------------------------ - void - RemoveInvalidLocations (const ArchSpec &arch); - - void - SetEnabledAll (bool enabled); - - //------------------------------------------------------------------ - /// Removes all the breakpoints from this list. - //------------------------------------------------------------------ - void - RemoveAll (bool notify); - - //------------------------------------------------------------------ - /// Tell all the breakpoints to update themselves due to a change in the - /// modules in \a module_list. \a added says whether the module was loaded - /// or unloaded. - /// - /// @param[in] module_list - /// The module list that has changed. - /// - /// @param[in] load - /// \b true if the modules are loaded, \b false if unloaded. - /// - /// @param[in] delete_locations - /// If \a load is \b false, then delete breakpoint locations when - /// when updating breakpoints. - //------------------------------------------------------------------ - void - UpdateBreakpoints (ModuleList &module_list, - bool load, - bool delete_locations); - - void - UpdateBreakpointsWhenModuleIsReplaced (lldb::ModuleSP old_module_sp, lldb::ModuleSP new_module_sp); - - void - ClearAllBreakpointSites (); - - //------------------------------------------------------------------ - /// Sets the passed in Locker to hold the Breakpoint List mutex. - /// - /// @param[in] locker - /// The locker object that is set. - //------------------------------------------------------------------ - void - GetListMutex(std::unique_lock<std::recursive_mutex> &lock); + BreakpointList(bool is_internal); + + ~BreakpointList(); + + //------------------------------------------------------------------ + /// Add the breakpoint \a bp_sp to the list. + /// + /// @param[in] bp_sp + /// Shared pointer to the breakpoint that will get added to the list. + /// + /// @result + /// Returns breakpoint id. + //------------------------------------------------------------------ + lldb::break_id_t Add(lldb::BreakpointSP &bp_sp, bool notify); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void Dump(Stream *s) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with id \a breakID. + /// + /// @param[in] breakID + /// The breakpoint ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointSP FindBreakpointByID(lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with id \a breakID. Const + /// version. + /// + /// @param[in] breakID + /// The breakpoint ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointSP FindBreakpointByID(lldb::break_id_t breakID) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with index \a i. + /// + /// @param[in] i + /// The breakpoint index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointSP GetBreakpointAtIndex(size_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with index \a i, const version + /// + /// @param[in] i + /// The breakpoint index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const; + + //------------------------------------------------------------------ + /// Find all the breakpoints with a given name + /// + /// @param[in] name + /// The breakpoint name for which to search. + /// + /// @result + /// \bfalse if the input name was not a legal breakpoint name. + //------------------------------------------------------------------ + bool FindBreakpointsByName(const char *name, BreakpointList &matching_bps); + + //------------------------------------------------------------------ + /// Returns the number of elements in this breakpoint list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t GetSize() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_breakpoints.size(); + } + + //------------------------------------------------------------------ + /// Removes the breakpoint given by \b breakID from this list. + /// + /// @param[in] breakID + /// The breakpoint index to remove. + /// + /// @result + /// \b true if the breakpoint \a breakID was in the list. + //------------------------------------------------------------------ + bool Remove(lldb::break_id_t breakID, bool notify); + + //------------------------------------------------------------------ + /// Removes all invalid breakpoint locations. + /// + /// Removes all breakpoint locations in the list with architectures + /// that aren't compatible with \a arch. Also remove any breakpoint + /// locations with whose locations have address where the section + /// has been deleted (module and object files no longer exist). + /// + /// This is typically used after the process calls exec, or anytime + /// the architecture of the target changes. + /// + /// @param[in] arch + /// If valid, check the module in each breakpoint to make sure + /// they are compatible, otherwise, ignore architecture. + //------------------------------------------------------------------ + void RemoveInvalidLocations(const ArchSpec &arch); + + void SetEnabledAll(bool enabled); + + //------------------------------------------------------------------ + /// Removes all the breakpoints from this list. + //------------------------------------------------------------------ + void RemoveAll(bool notify); + + //------------------------------------------------------------------ + /// Tell all the breakpoints to update themselves due to a change in the + /// modules in \a module_list. \a added says whether the module was loaded + /// or unloaded. + /// + /// @param[in] module_list + /// The module list that has changed. + /// + /// @param[in] load + /// \b true if the modules are loaded, \b false if unloaded. + /// + /// @param[in] delete_locations + /// If \a load is \b false, then delete breakpoint locations when + /// when updating breakpoints. + //------------------------------------------------------------------ + void UpdateBreakpoints(ModuleList &module_list, bool load, + bool delete_locations); + + void UpdateBreakpointsWhenModuleIsReplaced(lldb::ModuleSP old_module_sp, + lldb::ModuleSP new_module_sp); + + void ClearAllBreakpointSites(); + + //------------------------------------------------------------------ + /// Sets the passed in Locker to hold the Breakpoint List mutex. + /// + /// @param[in] locker + /// The locker object that is set. + //------------------------------------------------------------------ + void GetListMutex(std::unique_lock<std::recursive_mutex> &lock); protected: - typedef std::list<lldb::BreakpointSP> bp_collection; + typedef std::list<lldb::BreakpointSP> bp_collection; - bp_collection::iterator - GetBreakpointIDIterator(lldb::break_id_t breakID); + bp_collection::iterator GetBreakpointIDIterator(lldb::break_id_t breakID); - bp_collection::const_iterator - GetBreakpointIDConstIterator(lldb::break_id_t breakID) const; + bp_collection::const_iterator + GetBreakpointIDConstIterator(lldb::break_id_t breakID) const; - std::recursive_mutex & - GetMutex() const - { - return m_mutex; - } + std::recursive_mutex &GetMutex() const { return m_mutex; } - mutable std::recursive_mutex m_mutex; - bp_collection m_breakpoints; // The breakpoint list, currently a list. - lldb::break_id_t m_next_break_id; - bool m_is_internal; + mutable std::recursive_mutex m_mutex; + bp_collection m_breakpoints; // The breakpoint list, currently a list. + lldb::break_id_t m_next_break_id; + bool m_is_internal; public: - typedef LockingAdaptedIterable<bp_collection, lldb::BreakpointSP, list_adapter, std::recursive_mutex> - BreakpointIterable; - BreakpointIterable - Breakpoints() - { - return BreakpointIterable(m_breakpoints, GetMutex()); - } + typedef LockingAdaptedIterable<bp_collection, lldb::BreakpointSP, + list_adapter, std::recursive_mutex> + BreakpointIterable; + BreakpointIterable Breakpoints() { + return BreakpointIterable(m_breakpoints, GetMutex()); + } private: - DISALLOW_COPY_AND_ASSIGN (BreakpointList); + DISALLOW_COPY_AND_ASSIGN(BreakpointList); }; } // namespace lldb_private -#endif // liblldb_BreakpointList_h_ +#endif // liblldb_BreakpointList_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h index 42eca73dbb22..43aef9fc6a27 100644 --- a/include/lldb/Breakpoint/BreakpointLocation.h +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -17,16 +17,18 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Breakpoint/StoppointLocation.h" #include "lldb/Core/Address.h" #include "lldb/Core/UserID.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointLocation BreakpointLocation.h "lldb/Breakpoint/BreakpointLocation.h" -/// @brief Class that manages one unique (by address) instance of a logical breakpoint. +/// @class BreakpointLocation BreakpointLocation.h +/// "lldb/Breakpoint/BreakpointLocation.h" +/// @brief Class that manages one unique (by address) instance of a logical +/// breakpoint. //---------------------------------------------------------------------- //---------------------------------------------------------------------- @@ -42,438 +44,384 @@ namespace lldb_private { /// would be useful if you've set options on the locations. //---------------------------------------------------------------------- -class BreakpointLocation : - public std::enable_shared_from_this<BreakpointLocation>, - public StoppointLocation -{ +class BreakpointLocation + : public std::enable_shared_from_this<BreakpointLocation>, + public StoppointLocation { public: - ~BreakpointLocation() override; - - //------------------------------------------------------------------ - /// Gets the load address for this breakpoint location - /// @return - /// Returns breakpoint location load address, \b - /// LLDB_INVALID_ADDRESS if not yet set. - //------------------------------------------------------------------ - lldb::addr_t - GetLoadAddress() const override; - - //------------------------------------------------------------------ - /// Gets the Address for this breakpoint location - /// @return - /// Returns breakpoint location Address. - //------------------------------------------------------------------ - Address & - GetAddress (); - //------------------------------------------------------------------ - /// Gets the Breakpoint that created this breakpoint location - /// @return - /// Returns the owning breakpoint. - //------------------------------------------------------------------ - Breakpoint & - GetBreakpoint (); - - Target & - GetTarget(); - - //------------------------------------------------------------------ - /// Determines whether we should stop due to a hit at this - /// breakpoint location. - /// - /// Side Effects: This may evaluate the breakpoint condition, and - /// run the callback. So this command may do a considerable amount - /// of work. - /// - /// @return - /// \b true if this breakpoint location thinks we should stop, - /// \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldStop(StoppointCallbackContext *context) override; - - //------------------------------------------------------------------ - // The next section deals with various breakpoint options. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// If \a enable is \b true, enable the breakpoint, if \b false - /// disable it. - //------------------------------------------------------------------ - void - SetEnabled(bool enabled); - - //------------------------------------------------------------------ - /// Check the Enable/Disable state. - /// - /// @return - /// \b true if the breakpoint is enabled, \b false if disabled. - //------------------------------------------------------------------ - bool - IsEnabled () const; - - //------------------------------------------------------------------ - /// Return the current Ignore Count. - /// - /// @return - /// The number of breakpoint hits to be ignored. - //------------------------------------------------------------------ - uint32_t - GetIgnoreCount (); - - //------------------------------------------------------------------ - /// Set the breakpoint to ignore the next \a count breakpoint hits. - /// - /// @param[in] count - /// The number of breakpoint hits to ignore. - //------------------------------------------------------------------ - void - SetIgnoreCount (uint32_t n); - - //------------------------------------------------------------------ - /// Set the callback action invoked when the breakpoint is hit. - /// - /// The callback will return a bool indicating whether the target - /// should stop at this breakpoint or not. - /// - /// @param[in] callback - /// The method that will get called when the breakpoint is hit. - /// - /// @param[in] callback_baton_sp - /// A shared pointer to a Baton that provides the void * needed - /// for the callback. - /// - /// @see lldb_private::Baton - //------------------------------------------------------------------ - void - SetCallback (BreakpointHitCallback callback, - const lldb::BatonSP &callback_baton_sp, - bool is_synchronous); - - void - SetCallback (BreakpointHitCallback callback, - void *baton, - bool is_synchronous); - - void - ClearCallback (); - - //------------------------------------------------------------------ - /// Set the breakpoint location's condition. - /// - /// @param[in] condition - /// The condition expression to evaluate when the breakpoint is hit. - //------------------------------------------------------------------ - void - SetCondition (const char *condition); - - //------------------------------------------------------------------ - /// Return a pointer to the text of the condition expression. - /// - /// @return - /// A pointer to the condition expression text, or nullptr if no - // condition has been set. - //------------------------------------------------------------------ - const char * - GetConditionText(size_t *hash = nullptr) const; - - bool - ConditionSaysStop (ExecutionContext &exe_ctx, Error &error); - - //------------------------------------------------------------------ - /// Set the valid thread to be checked when the breakpoint is hit. - /// - /// @param[in] thread_id - /// If this thread hits the breakpoint, we stop, otherwise not. - //------------------------------------------------------------------ - void - SetThreadID (lldb::tid_t thread_id); - - lldb::tid_t - GetThreadID (); - - void - SetThreadIndex (uint32_t index); - - uint32_t - GetThreadIndex() const; - - void - SetThreadName (const char *thread_name); - - const char * - GetThreadName () const; - - void - SetQueueName (const char *queue_name); - - const char * - GetQueueName () const; - - //------------------------------------------------------------------ - // The next section deals with this location's breakpoint sites. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Try to resolve the breakpoint site for this location. - /// - /// @return - /// \b true if we were successful at setting a breakpoint site, - /// \b false otherwise. - //------------------------------------------------------------------ - bool - ResolveBreakpointSite (); - - //------------------------------------------------------------------ - /// Clear this breakpoint location's breakpoint site - for instance - /// when disabling the breakpoint. - /// - /// @return - /// \b true if there was a breakpoint site to be cleared, \b false - /// otherwise. - //------------------------------------------------------------------ - bool - ClearBreakpointSite (); - - //------------------------------------------------------------------ - /// Return whether this breakpoint location has a breakpoint site. - /// @return - /// \b true if there was a breakpoint site for this breakpoint - /// location, \b false otherwise. - //------------------------------------------------------------------ - bool - IsResolved () const; - - lldb::BreakpointSiteSP - GetBreakpointSite() const; - - //------------------------------------------------------------------ - // The next section are generic report functions. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Print a description of this breakpoint location to the stream - /// \a s. - /// - /// @param[in] s - /// The stream to which to print the description. - /// - /// @param[in] level - /// The description level that indicates the detail level to - /// provide. - /// - /// @see lldb::DescriptionLevel - //------------------------------------------------------------------ - void - GetDescription (Stream *s, lldb::DescriptionLevel level); - - //------------------------------------------------------------------ - /// Standard "Dump" method. At present it does nothing. - //------------------------------------------------------------------ - void - Dump(Stream *s) const override; - - //------------------------------------------------------------------ - /// Use this to set location specific breakpoint options. - /// - /// It will create a copy of the containing breakpoint's options if - /// that hasn't been done already - /// - /// @return - /// A pointer to the breakpoint options. - //------------------------------------------------------------------ - BreakpointOptions * - GetLocationOptions (); - - //------------------------------------------------------------------ - /// Use this to access breakpoint options from this breakpoint location. - /// This will point to the owning breakpoint's options unless options have - /// been set specifically on this location. - /// - /// @return - /// A pointer to the containing breakpoint's options if this - /// location doesn't have its own copy. - //------------------------------------------------------------------ - const BreakpointOptions * - GetOptionsNoCreate () const; - - bool - ValidForThisThread (Thread *thread); - - //------------------------------------------------------------------ - /// Invoke the callback action when the breakpoint is hit. - /// - /// Meant to be used by the BreakpointLocation class. - /// - /// @param[in] context - /// Described the breakpoint event. - /// - /// @param[in] bp_loc_id - /// Which breakpoint location hit this breakpoint. - /// - /// @return - /// \b true if the target should stop at this breakpoint and \b - /// false not. - //------------------------------------------------------------------ - bool - InvokeCallback (StoppointCallbackContext *context); - - //------------------------------------------------------------------ - /// Returns whether we should resolve Indirect functions in setting the breakpoint site - /// for this location. - /// - /// @return - /// \b true if the breakpoint SITE for this location should be set on the - /// resolved location for Indirect functions. - //------------------------------------------------------------------ - bool - ShouldResolveIndirectFunctions () - { - return m_should_resolve_indirect_functions; - } - - //------------------------------------------------------------------ - /// Returns whether the address set in the breakpoint site for this location was found by resolving - /// an indirect symbol. - /// - /// @return - /// \b true or \b false as given in the description above. - //------------------------------------------------------------------ - bool - IsIndirect () - { - return m_is_indirect; - } - - void - SetIsIndirect (bool is_indirect) - { - m_is_indirect = is_indirect; - } - - //------------------------------------------------------------------ - /// Returns whether the address set in the breakpoint location was re-routed to the target of a - /// re-exported symbol. - /// - /// @return - /// \b true or \b false as given in the description above. - //------------------------------------------------------------------ - bool - IsReExported () - { - return m_is_reexported; - } - - void - SetIsReExported (bool is_reexported) - { - m_is_reexported = is_reexported; - } - - //------------------------------------------------------------------ - /// Returns whether the two breakpoint locations might represent "equivalent locations". - /// This is used when modules changed to determine if a Location in the old module might - /// be the "same as" the input location. - /// - /// @param[in] location - /// The location to compare against. - /// - /// @return - /// \b true or \b false as given in the description above. - //------------------------------------------------------------------ - bool EquivalentToLocation(BreakpointLocation &location); - + ~BreakpointLocation() override; + + //------------------------------------------------------------------ + /// Gets the load address for this breakpoint location + /// @return + /// Returns breakpoint location load address, \b + /// LLDB_INVALID_ADDRESS if not yet set. + //------------------------------------------------------------------ + lldb::addr_t GetLoadAddress() const override; + + //------------------------------------------------------------------ + /// Gets the Address for this breakpoint location + /// @return + /// Returns breakpoint location Address. + //------------------------------------------------------------------ + Address &GetAddress(); + //------------------------------------------------------------------ + /// Gets the Breakpoint that created this breakpoint location + /// @return + /// Returns the owning breakpoint. + //------------------------------------------------------------------ + Breakpoint &GetBreakpoint(); + + Target &GetTarget(); + + //------------------------------------------------------------------ + /// Determines whether we should stop due to a hit at this + /// breakpoint location. + /// + /// Side Effects: This may evaluate the breakpoint condition, and + /// run the callback. So this command may do a considerable amount + /// of work. + /// + /// @return + /// \b true if this breakpoint location thinks we should stop, + /// \b false otherwise. + //------------------------------------------------------------------ + bool ShouldStop(StoppointCallbackContext *context) override; + + //------------------------------------------------------------------ + // The next section deals with various breakpoint options. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false + /// disable it. + //------------------------------------------------------------------ + void SetEnabled(bool enabled); + + //------------------------------------------------------------------ + /// Check the Enable/Disable state. + /// + /// @return + /// \b true if the breakpoint is enabled, \b false if disabled. + //------------------------------------------------------------------ + bool IsEnabled() const; + + //------------------------------------------------------------------ + /// Return the current Ignore Count. + /// + /// @return + /// The number of breakpoint hits to be ignored. + //------------------------------------------------------------------ + uint32_t GetIgnoreCount(); + + //------------------------------------------------------------------ + /// Set the breakpoint to ignore the next \a count breakpoint hits. + /// + /// @param[in] count + /// The number of breakpoint hits to ignore. + //------------------------------------------------------------------ + void SetIgnoreCount(uint32_t n); + + //------------------------------------------------------------------ + /// Set the callback action invoked when the breakpoint is hit. + /// + /// The callback will return a bool indicating whether the target + /// should stop at this breakpoint or not. + /// + /// @param[in] callback + /// The method that will get called when the breakpoint is hit. + /// + /// @param[in] callback_baton_sp + /// A shared pointer to a Baton that provides the void * needed + /// for the callback. + /// + /// @see lldb_private::Baton + //------------------------------------------------------------------ + void SetCallback(BreakpointHitCallback callback, + const lldb::BatonSP &callback_baton_sp, bool is_synchronous); + + void SetCallback(BreakpointHitCallback callback, void *baton, + bool is_synchronous); + + void ClearCallback(); + + //------------------------------------------------------------------ + /// Set the breakpoint location's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the breakpoint is hit. + //------------------------------------------------------------------ + void SetCondition(const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or nullptr if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText(size_t *hash = nullptr) const; + + bool ConditionSaysStop(ExecutionContext &exe_ctx, Error &error); + + //------------------------------------------------------------------ + /// Set the valid thread to be checked when the breakpoint is hit. + /// + /// @param[in] thread_id + /// If this thread hits the breakpoint, we stop, otherwise not. + //------------------------------------------------------------------ + void SetThreadID(lldb::tid_t thread_id); + + lldb::tid_t GetThreadID(); + + void SetThreadIndex(uint32_t index); + + uint32_t GetThreadIndex() const; + + void SetThreadName(const char *thread_name); + + const char *GetThreadName() const; + + void SetQueueName(const char *queue_name); + + const char *GetQueueName() const; + + //------------------------------------------------------------------ + // The next section deals with this location's breakpoint sites. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Try to resolve the breakpoint site for this location. + /// + /// @return + /// \b true if we were successful at setting a breakpoint site, + /// \b false otherwise. + //------------------------------------------------------------------ + bool ResolveBreakpointSite(); + + //------------------------------------------------------------------ + /// Clear this breakpoint location's breakpoint site - for instance + /// when disabling the breakpoint. + /// + /// @return + /// \b true if there was a breakpoint site to be cleared, \b false + /// otherwise. + //------------------------------------------------------------------ + bool ClearBreakpointSite(); + + //------------------------------------------------------------------ + /// Return whether this breakpoint location has a breakpoint site. + /// @return + /// \b true if there was a breakpoint site for this breakpoint + /// location, \b false otherwise. + //------------------------------------------------------------------ + bool IsResolved() const; + + lldb::BreakpointSiteSP GetBreakpointSite() const; + + //------------------------------------------------------------------ + // The next section are generic report functions. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Print a description of this breakpoint location to the stream + /// \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription(Stream *s, lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void Dump(Stream *s) const override; + + //------------------------------------------------------------------ + /// Use this to set location specific breakpoint options. + /// + /// It will create a copy of the containing breakpoint's options if + /// that hasn't been done already + /// + /// @return + /// A pointer to the breakpoint options. + //------------------------------------------------------------------ + BreakpointOptions *GetLocationOptions(); + + //------------------------------------------------------------------ + /// Use this to access breakpoint options from this breakpoint location. + /// This will point to the owning breakpoint's options unless options have + /// been set specifically on this location. + /// + /// @return + /// A pointer to the containing breakpoint's options if this + /// location doesn't have its own copy. + //------------------------------------------------------------------ + const BreakpointOptions *GetOptionsNoCreate() const; + + bool ValidForThisThread(Thread *thread); + + //------------------------------------------------------------------ + /// Invoke the callback action when the breakpoint is hit. + /// + /// Meant to be used by the BreakpointLocation class. + /// + /// @param[in] context + /// Described the breakpoint event. + /// + /// @param[in] bp_loc_id + /// Which breakpoint location hit this breakpoint. + /// + /// @return + /// \b true if the target should stop at this breakpoint and \b + /// false not. + //------------------------------------------------------------------ + bool InvokeCallback(StoppointCallbackContext *context); + + //------------------------------------------------------------------ + /// Returns whether we should resolve Indirect functions in setting the + /// breakpoint site + /// for this location. + /// + /// @return + /// \b true if the breakpoint SITE for this location should be set on the + /// resolved location for Indirect functions. + //------------------------------------------------------------------ + bool ShouldResolveIndirectFunctions() { + return m_should_resolve_indirect_functions; + } + + //------------------------------------------------------------------ + /// Returns whether the address set in the breakpoint site for this location + /// was found by resolving + /// an indirect symbol. + /// + /// @return + /// \b true or \b false as given in the description above. + //------------------------------------------------------------------ + bool IsIndirect() { return m_is_indirect; } + + void SetIsIndirect(bool is_indirect) { m_is_indirect = is_indirect; } + + //------------------------------------------------------------------ + /// Returns whether the address set in the breakpoint location was re-routed + /// to the target of a + /// re-exported symbol. + /// + /// @return + /// \b true or \b false as given in the description above. + //------------------------------------------------------------------ + bool IsReExported() { return m_is_reexported; } + + void SetIsReExported(bool is_reexported) { m_is_reexported = is_reexported; } + + //------------------------------------------------------------------ + /// Returns whether the two breakpoint locations might represent "equivalent + /// locations". + /// This is used when modules changed to determine if a Location in the old + /// module might + /// be the "same as" the input location. + /// + /// @param[in] location + /// The location to compare against. + /// + /// @return + /// \b true or \b false as given in the description above. + //------------------------------------------------------------------ + bool EquivalentToLocation(BreakpointLocation &location); + protected: - friend class BreakpointSite; - friend class BreakpointLocationList; - friend class Process; - friend class StopInfoBreakpoint; - - //------------------------------------------------------------------ - /// Set the breakpoint site for this location to \a bp_site_sp. - /// - /// @param[in] bp_site_sp - /// The breakpoint site we are setting for this location. - /// - /// @return - /// \b true if we were successful at setting the breakpoint site, - /// \b false otherwise. - //------------------------------------------------------------------ - bool - SetBreakpointSite (lldb::BreakpointSiteSP& bp_site_sp); - - void - DecrementIgnoreCount(); - - bool - IgnoreCountShouldStop(); - + friend class BreakpointSite; + friend class BreakpointLocationList; + friend class Process; + friend class StopInfoBreakpoint; + + //------------------------------------------------------------------ + /// Set the breakpoint site for this location to \a bp_site_sp. + /// + /// @param[in] bp_site_sp + /// The breakpoint site we are setting for this location. + /// + /// @return + /// \b true if we were successful at setting the breakpoint site, + /// \b false otherwise. + //------------------------------------------------------------------ + bool SetBreakpointSite(lldb::BreakpointSiteSP &bp_site_sp); + + void DecrementIgnoreCount(); + + bool IgnoreCountShouldStop(); + private: - void - SwapLocation (lldb::BreakpointLocationSP swap_from); - - void - BumpHitCount(); - - void - UndoBumpHitCount(); - - //------------------------------------------------------------------ - // Constructors and Destructors - // - // Only the Breakpoint can make breakpoint locations, and it owns - // them. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Constructor. - /// - /// @param[in] owner - /// A back pointer to the breakpoint that owns this location. - /// - /// @param[in] addr - /// The Address defining this location. - /// - /// @param[in] tid - /// The thread for which this breakpoint location is valid, or - /// LLDB_INVALID_THREAD_ID if it is valid for all threads. - /// - /// @param[in] hardware - /// \b true if a hardware breakpoint is requested. - //------------------------------------------------------------------ - - BreakpointLocation (lldb::break_id_t bid, - Breakpoint &owner, - const Address &addr, - lldb::tid_t tid, - bool hardware, - bool check_for_resolver = true); - - //------------------------------------------------------------------ - // Data members: - //------------------------------------------------------------------ - bool m_being_created; - bool m_should_resolve_indirect_functions; - bool m_is_reexported; - bool m_is_indirect; - Address m_address; ///< The address defining this location. - Breakpoint &m_owner; ///< The breakpoint that produced this object. - std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, nullptr if we're using our breakpoint's options. - lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.) - lldb::UserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition. - std::mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by - /// multiple processes. - size_t m_condition_hash; ///< For testing whether the condition source code changed. - - void - SetShouldResolveIndirectFunctions (bool do_resolve) - { - m_should_resolve_indirect_functions = do_resolve; - } - - void - SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind); - - DISALLOW_COPY_AND_ASSIGN (BreakpointLocation); + void SwapLocation(lldb::BreakpointLocationSP swap_from); + + void BumpHitCount(); + + void UndoBumpHitCount(); + + //------------------------------------------------------------------ + // Constructors and Destructors + // + // Only the Breakpoint can make breakpoint locations, and it owns + // them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Constructor. + /// + /// @param[in] owner + /// A back pointer to the breakpoint that owns this location. + /// + /// @param[in] addr + /// The Address defining this location. + /// + /// @param[in] tid + /// The thread for which this breakpoint location is valid, or + /// LLDB_INVALID_THREAD_ID if it is valid for all threads. + /// + /// @param[in] hardware + /// \b true if a hardware breakpoint is requested. + //------------------------------------------------------------------ + + BreakpointLocation(lldb::break_id_t bid, Breakpoint &owner, + const Address &addr, lldb::tid_t tid, bool hardware, + bool check_for_resolver = true); + + //------------------------------------------------------------------ + // Data members: + //------------------------------------------------------------------ + bool m_being_created; + bool m_should_resolve_indirect_functions; + bool m_is_reexported; + bool m_is_indirect; + Address m_address; ///< The address defining this location. + Breakpoint &m_owner; ///< The breakpoint that produced this object. + std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options + ///pointer, nullptr if we're + ///using our breakpoint's + ///options. + lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be + ///shared by more than one location.) + lldb::UserExpressionSP m_user_expression_sp; ///< The compiled expression to + ///use in testing our condition. + std::mutex m_condition_mutex; ///< Guards parsing and evaluation of the + ///condition, which could be evaluated by + /// multiple processes. + size_t m_condition_hash; ///< For testing whether the condition source code + ///changed. + + void SetShouldResolveIndirectFunctions(bool do_resolve) { + m_should_resolve_indirect_functions = do_resolve; + } + + void SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind); + + DISALLOW_COPY_AND_ASSIGN(BreakpointLocation); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointLocationCollection.h b/include/lldb/Breakpoint/BreakpointLocationCollection.h index 1a016544fa4c..4b2d9d4b344d 100644 --- a/include/lldb/Breakpoint/BreakpointLocationCollection.h +++ b/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -12,210 +12,202 @@ // C Includes // C++ Includes -#include <vector> #include <mutex> +#include <vector> // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Utility/Iterable.h" +#include "lldb/lldb-private.h" namespace lldb_private { -class BreakpointLocationCollection -{ +class BreakpointLocationCollection { public: - BreakpointLocationCollection(); - - ~BreakpointLocationCollection(); - - //------------------------------------------------------------------ - /// Add the breakpoint \a bp_loc_sp to the list. - /// - /// @param[in] bp_sp - /// Shared pointer to the breakpoint location that will get added - /// to the list. - /// - /// @result - /// Returns breakpoint location id. - //------------------------------------------------------------------ - void - Add (const lldb::BreakpointLocationSP& bp_loc_sp); - - //------------------------------------------------------------------ - /// Removes the breakpoint location given by \b breakID from this - /// list. - /// - /// @param[in] break_id - /// The breakpoint index to remove. - /// - /// @param[in] break_loc_id - /// The breakpoint location index in break_id to remove. - /// - /// @result - /// \b true if the breakpoint was in the list. - //------------------------------------------------------------------ - bool - Remove (lldb::break_id_t break_id, lldb::break_id_t break_loc_id); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with id \a - /// breakID. - /// - /// @param[in] break_id - /// The breakpoint ID to seek for. - /// - /// @param[in] break_loc_id - /// The breakpoint location ID in \a break_id to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with id \a - /// breakID, const version. - /// - /// @param[in] breakID - /// The breakpoint location ID to seek for. - /// - /// @param[in] break_loc_id - /// The breakpoint location ID in \a break_id to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointLocationSP - FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with index - /// \a i. - /// - /// @param[in] i - /// The breakpoint location index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - GetByIndex (size_t i); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with index - /// \a i, const version. - /// - /// @param[in] i - /// The breakpoint location index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a NULL - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointLocationSP - GetByIndex (size_t i) const; - - //------------------------------------------------------------------ - /// Returns the number of elements in this breakpoint location list. - /// - /// @result - /// The number of elements. - //------------------------------------------------------------------ - size_t - GetSize() const { return m_break_loc_collection.size(); } - - //------------------------------------------------------------------ - /// Enquires of all the breakpoint locations in this list whether - /// we should stop at a hit at \a breakID. - /// - /// @param[in] context - /// This contains the information about this stop. - /// - /// @param[in] breakID - /// This break ID that we hit. - /// - /// @return - /// \b true if we should stop, \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldStop (StoppointCallbackContext *context); - - //------------------------------------------------------------------ - /// Print a description of the breakpoint locations in this list - /// to the stream \a s. - /// - /// @param[in] s - /// The stream to which to print the description. - /// - /// @param[in] level - /// The description level that indicates the detail level to - /// provide. - /// - /// @see lldb::DescriptionLevel - //------------------------------------------------------------------ - void GetDescription (Stream *s, lldb::DescriptionLevel level); - - //------------------------------------------------------------------ - /// Check whether this collection of breakpoint locations have any - /// thread specifiers, and if yes, is \a thread_id contained in any - /// of these specifiers. - /// - /// @param[in] thread - /// The thread against which to test. - /// - /// return - /// \b true if the collection contains at least one location that - /// would be valid for this thread, false otherwise. - //------------------------------------------------------------------ - bool ValidForThisThread (Thread *thread); - - //------------------------------------------------------------------ - /// Tell whether ALL the breakpoints in the location collection are internal. - /// - /// @result - /// \b true if all breakpoint locations are owned by internal breakpoints, - /// \b false otherwise. - //------------------------------------------------------------------ - bool IsInternal() const; - + BreakpointLocationCollection(); + + ~BreakpointLocationCollection(); + + //------------------------------------------------------------------ + /// Add the breakpoint \a bp_loc_sp to the list. + /// + /// @param[in] bp_sp + /// Shared pointer to the breakpoint location that will get added + /// to the list. + /// + /// @result + /// Returns breakpoint location id. + //------------------------------------------------------------------ + void Add(const lldb::BreakpointLocationSP &bp_loc_sp); + + //------------------------------------------------------------------ + /// Removes the breakpoint location given by \b breakID from this + /// list. + /// + /// @param[in] break_id + /// The breakpoint index to remove. + /// + /// @param[in] break_loc_id + /// The breakpoint location index in break_id to remove. + /// + /// @result + /// \b true if the breakpoint was in the list. + //------------------------------------------------------------------ + bool Remove(lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with id \a + /// breakID. + /// + /// @param[in] break_id + /// The breakpoint ID to seek for. + /// + /// @param[in] break_loc_id + /// The breakpoint location ID in \a break_id to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP FindByIDPair(lldb::break_id_t break_id, + lldb::break_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with id \a + /// breakID, const version. + /// + /// @param[in] breakID + /// The breakpoint location ID to seek for. + /// + /// @param[in] break_loc_id + /// The breakpoint location ID in \a break_id to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP + FindByIDPair(lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with index + /// \a i. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP GetByIndex(size_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with index + /// \a i, const version. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP GetByIndex(size_t i) const; + + //------------------------------------------------------------------ + /// Returns the number of elements in this breakpoint location list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t GetSize() const { return m_break_loc_collection.size(); } + + //------------------------------------------------------------------ + /// Enquires of all the breakpoint locations in this list whether + /// we should stop at a hit at \a breakID. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] breakID + /// This break ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool ShouldStop(StoppointCallbackContext *context); + + //------------------------------------------------------------------ + /// Print a description of the breakpoint locations in this list + /// to the stream \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription(Stream *s, lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Check whether this collection of breakpoint locations have any + /// thread specifiers, and if yes, is \a thread_id contained in any + /// of these specifiers. + /// + /// @param[in] thread + /// The thread against which to test. + /// + /// return + /// \b true if the collection contains at least one location that + /// would be valid for this thread, false otherwise. + //------------------------------------------------------------------ + bool ValidForThisThread(Thread *thread); + + //------------------------------------------------------------------ + /// Tell whether ALL the breakpoints in the location collection are internal. + /// + /// @result + /// \b true if all breakpoint locations are owned by internal breakpoints, + /// \b false otherwise. + //------------------------------------------------------------------ + bool IsInternal() const; protected: - //------------------------------------------------------------------ - // Classes that inherit from BreakpointLocationCollection can see - // and modify these - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Classes that inherit from BreakpointLocationCollection can see + // and modify these + //------------------------------------------------------------------ private: - //------------------------------------------------------------------ - // For BreakpointLocationCollection only - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // For BreakpointLocationCollection only + //------------------------------------------------------------------ - typedef std::vector<lldb::BreakpointLocationSP> collection; + typedef std::vector<lldb::BreakpointLocationSP> collection; - collection::iterator - GetIDPairIterator(lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + collection::iterator GetIDPairIterator(lldb::break_id_t break_id, + lldb::break_id_t break_loc_id); - collection::const_iterator - GetIDPairConstIterator(lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const; + collection::const_iterator + GetIDPairConstIterator(lldb::break_id_t break_id, + lldb::break_id_t break_loc_id) const; - collection m_break_loc_collection; - mutable std::mutex m_collection_mutex; + collection m_break_loc_collection; + mutable std::mutex m_collection_mutex; public: - typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, vector_adapter> BreakpointLocationCollectionIterable; - BreakpointLocationCollectionIterable - BreakpointLocations() - { - return BreakpointLocationCollectionIterable(m_break_loc_collection); - } - + typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, + vector_adapter> + BreakpointLocationCollectionIterable; + BreakpointLocationCollectionIterable BreakpointLocations() { + return BreakpointLocationCollectionIterable(m_break_loc_collection); + } }; } // namespace lldb_private -#endif // liblldb_BreakpointLocationCollection_h_ +#endif // liblldb_BreakpointLocationCollection_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h index 1fbfa43a40f4..46eb2612bbe8 100644 --- a/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/include/lldb/Breakpoint/BreakpointLocationList.h @@ -18,270 +18,248 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Utility/Iterable.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointLocationList BreakpointLocationList.h "lldb/Breakpoint/BreakpointLocationList.h" -/// @brief This class is used by Breakpoint to manage a list of breakpoint locations, +/// @class BreakpointLocationList BreakpointLocationList.h +/// "lldb/Breakpoint/BreakpointLocationList.h" +/// @brief This class is used by Breakpoint to manage a list of breakpoint +/// locations, // each breakpoint location in the list /// has a unique ID, and is unique by Address as well. //---------------------------------------------------------------------- -class BreakpointLocationList -{ -// Only Breakpoints can make the location list, or add elements to it. -// This is not just some random collection of locations. Rather, the act of adding the location -// to this list sets its ID, and implicitly all the locations have the same breakpoint ID as -// well. If you need a generic container for breakpoint locations, use BreakpointLocationCollection. -friend class Breakpoint; +class BreakpointLocationList { + // Only Breakpoints can make the location list, or add elements to it. + // This is not just some random collection of locations. Rather, the act of + // adding the location + // to this list sets its ID, and implicitly all the locations have the same + // breakpoint ID as + // well. If you need a generic container for breakpoint locations, use + // BreakpointLocationCollection. + friend class Breakpoint; public: - virtual - ~BreakpointLocationList(); - - //------------------------------------------------------------------ - /// Standard "Dump" method. At present it does nothing. - //------------------------------------------------------------------ - void - Dump (Stream *s) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location at address - /// \a addr - const version. - /// - /// @param[in] addr - /// The address to look for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a nullptr - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointLocationSP - FindByAddress (const Address &addr) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with id - /// \a breakID, const version. - /// - /// @param[in] breakID - /// The breakpoint location ID to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a nullptr - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - FindByID (lldb::break_id_t breakID) const; - - //------------------------------------------------------------------ - /// Returns the breakpoint location id to the breakpoint location - /// at address \a addr. - /// - /// @param[in] addr - /// The address to match. - /// - /// @result - /// The ID of the breakpoint location, or LLDB_INVALID_BREAK_ID. - //------------------------------------------------------------------ - lldb::break_id_t - FindIDByAddress (const Address &addr); - - //------------------------------------------------------------------ - /// Returns a breakpoint location list of the breakpoint locations - /// in the module \a module. This list is allocated, and owned by - /// the caller. - /// - /// @param[in] module - /// The module to seek in. - /// - /// @param[in] - /// A breakpoint collection that gets any breakpoint locations - /// that match \a module appended to. - /// - /// @result - /// The number of matches - //------------------------------------------------------------------ - size_t - FindInModule (Module *module, - BreakpointLocationCollection& bp_loc_list); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with - /// index \a i. - /// - /// @param[in] i - /// The breakpoint location index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a nullptr - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - GetByIndex (size_t i); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint location with index - /// \a i, const version. - /// - /// @param[in] i - /// The breakpoint location index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint. May contain a nullptr - /// pointer if the breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointLocationSP - GetByIndex (size_t i) const; - - //------------------------------------------------------------------ - /// Removes all the locations in this list from their breakpoint site - /// owners list. - //------------------------------------------------------------------ - void - ClearAllBreakpointSites (); - - //------------------------------------------------------------------ - /// Tells all the breakpoint locations in this list to attempt to - /// resolve any possible breakpoint sites. - //------------------------------------------------------------------ - void - ResolveAllBreakpointSites (); - - //------------------------------------------------------------------ - /// Returns the number of breakpoint locations in this list with - /// resolved breakpoints. - /// - /// @result - /// Number of qualifying breakpoint locations. - //------------------------------------------------------------------ - size_t - GetNumResolvedLocations() const; - - //------------------------------------------------------------------ - /// Returns the number hit count of all locations in this list. - /// - /// @result - /// Hit count of all locations in this list. - //------------------------------------------------------------------ - uint32_t - GetHitCount () const; - - //------------------------------------------------------------------ - /// Enquires of the breakpoint location in this list with ID \a - /// breakID whether we should stop. - /// - /// @param[in] context - /// This contains the information about this stop. - /// - /// @param[in] breakID - /// This break ID that we hit. - /// - /// @return - /// \b true if we should stop, \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldStop (StoppointCallbackContext *context, - lldb::break_id_t breakID); - - //------------------------------------------------------------------ - /// Returns the number of elements in this breakpoint location list. - /// - /// @result - /// The number of elements. - //------------------------------------------------------------------ - size_t - GetSize() const - { - return m_locations.size(); - } - - //------------------------------------------------------------------ - /// Print a description of the breakpoint locations in this list to - /// the stream \a s. - /// - /// @param[in] s - /// The stream to which to print the description. - /// - /// @param[in] level - /// The description level that indicates the detail level to - /// provide. - /// - /// @see lldb::DescriptionLevel - //------------------------------------------------------------------ - void - GetDescription (Stream *s, - lldb::DescriptionLevel level); + virtual ~BreakpointLocationList(); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void Dump(Stream *s) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location at address + /// \a addr - const version. + /// + /// @param[in] addr + /// The address to look for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a nullptr + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP FindByAddress(const Address &addr) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with id + /// \a breakID, const version. + /// + /// @param[in] breakID + /// The breakpoint location ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a nullptr + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP FindByID(lldb::break_id_t breakID) const; + + //------------------------------------------------------------------ + /// Returns the breakpoint location id to the breakpoint location + /// at address \a addr. + /// + /// @param[in] addr + /// The address to match. + /// + /// @result + /// The ID of the breakpoint location, or LLDB_INVALID_BREAK_ID. + //------------------------------------------------------------------ + lldb::break_id_t FindIDByAddress(const Address &addr); + + //------------------------------------------------------------------ + /// Returns a breakpoint location list of the breakpoint locations + /// in the module \a module. This list is allocated, and owned by + /// the caller. + /// + /// @param[in] module + /// The module to seek in. + /// + /// @param[in] + /// A breakpoint collection that gets any breakpoint locations + /// that match \a module appended to. + /// + /// @result + /// The number of matches + //------------------------------------------------------------------ + size_t FindInModule(Module *module, + BreakpointLocationCollection &bp_loc_list); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with + /// index \a i. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a nullptr + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP GetByIndex(size_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with index + /// \a i, const version. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a nullptr + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP GetByIndex(size_t i) const; + + //------------------------------------------------------------------ + /// Removes all the locations in this list from their breakpoint site + /// owners list. + //------------------------------------------------------------------ + void ClearAllBreakpointSites(); + + //------------------------------------------------------------------ + /// Tells all the breakpoint locations in this list to attempt to + /// resolve any possible breakpoint sites. + //------------------------------------------------------------------ + void ResolveAllBreakpointSites(); + + //------------------------------------------------------------------ + /// Returns the number of breakpoint locations in this list with + /// resolved breakpoints. + /// + /// @result + /// Number of qualifying breakpoint locations. + //------------------------------------------------------------------ + size_t GetNumResolvedLocations() const; + + //------------------------------------------------------------------ + /// Returns the number hit count of all locations in this list. + /// + /// @result + /// Hit count of all locations in this list. + //------------------------------------------------------------------ + uint32_t GetHitCount() const; + + //------------------------------------------------------------------ + /// Enquires of the breakpoint location in this list with ID \a + /// breakID whether we should stop. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] breakID + /// This break ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool ShouldStop(StoppointCallbackContext *context, lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns the number of elements in this breakpoint location list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t GetSize() const { return m_locations.size(); } + + //------------------------------------------------------------------ + /// Print a description of the breakpoint locations in this list to + /// the stream \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription(Stream *s, lldb::DescriptionLevel level); protected: - //------------------------------------------------------------------ - /// This is the standard constructor. - /// - /// It creates an empty breakpoint location list. It is protected - /// here because only Breakpoints are allowed to create the - /// breakpoint location list. - //------------------------------------------------------------------ - BreakpointLocationList(Breakpoint &owner); - - //------------------------------------------------------------------ - /// Add the breakpoint \a bp_loc_sp to the list. - /// - /// @param[in] bp_sp - /// Shared pointer to the breakpoint location that will get - /// added to the list. - /// - /// @result - /// Returns breakpoint location id. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - Create (const Address &addr, bool resolve_indirect_symbols); - - void - StartRecordingNewLocations(BreakpointLocationCollection &new_locations); - - void - StopRecordingNewLocations(); - - lldb::BreakpointLocationSP - AddLocation(const Address &addr, - bool resolve_indirect_symbols, - bool *new_location = nullptr); - - void - SwapLocation (lldb::BreakpointLocationSP to_location_sp, lldb::BreakpointLocationSP from_location_sp); - - bool - RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp); - - void - RemoveInvalidLocations (const ArchSpec &arch); - - void - Compact(); - - typedef std::vector<lldb::BreakpointLocationSP> collection; - typedef std::map<lldb_private::Address, - lldb::BreakpointLocationSP, - Address::ModulePointerAndOffsetLessThanFunctionObject> addr_map; - - Breakpoint &m_owner; - collection m_locations; // Vector of locations, sorted by ID - addr_map m_address_to_location; - mutable std::recursive_mutex m_mutex; - lldb::break_id_t m_next_id; - BreakpointLocationCollection *m_new_location_recorder; + //------------------------------------------------------------------ + /// This is the standard constructor. + /// + /// It creates an empty breakpoint location list. It is protected + /// here because only Breakpoints are allowed to create the + /// breakpoint location list. + //------------------------------------------------------------------ + BreakpointLocationList(Breakpoint &owner); + + //------------------------------------------------------------------ + /// Add the breakpoint \a bp_loc_sp to the list. + /// + /// @param[in] bp_sp + /// Shared pointer to the breakpoint location that will get + /// added to the list. + /// + /// @result + /// Returns breakpoint location id. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP Create(const Address &addr, + bool resolve_indirect_symbols); + + void StartRecordingNewLocations(BreakpointLocationCollection &new_locations); + + void StopRecordingNewLocations(); + + lldb::BreakpointLocationSP AddLocation(const Address &addr, + bool resolve_indirect_symbols, + bool *new_location = nullptr); + + void SwapLocation(lldb::BreakpointLocationSP to_location_sp, + lldb::BreakpointLocationSP from_location_sp); + + bool RemoveLocation(const lldb::BreakpointLocationSP &bp_loc_sp); + + void RemoveInvalidLocations(const ArchSpec &arch); + + void Compact(); + + typedef std::vector<lldb::BreakpointLocationSP> collection; + typedef std::map<lldb_private::Address, lldb::BreakpointLocationSP, + Address::ModulePointerAndOffsetLessThanFunctionObject> + addr_map; + + Breakpoint &m_owner; + collection m_locations; // Vector of locations, sorted by ID + addr_map m_address_to_location; + mutable std::recursive_mutex m_mutex; + lldb::break_id_t m_next_id; + BreakpointLocationCollection *m_new_location_recorder; public: - typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, vector_adapter> BreakpointLocationIterable; + typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, + vector_adapter> + BreakpointLocationIterable; - BreakpointLocationIterable - BreakpointLocations() - { - return BreakpointLocationIterable(m_locations); - } + BreakpointLocationIterable BreakpointLocations() { + return BreakpointLocationIterable(m_locations); + } }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointOptions.h b/include/lldb/Breakpoint/BreakpointOptions.h index e7882147a4da..e053af352ff2 100644 --- a/include/lldb/Breakpoint/BreakpointOptions.h +++ b/include/lldb/Breakpoint/BreakpointOptions.h @@ -17,341 +17,389 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Baton.h" #include "lldb/Core/StringList.h" +#include "lldb/Core/StructuredData.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointOptions BreakpointOptions.h "lldb/Breakpoint/BreakpointOptions.h" -/// @brief Class that manages the options on a breakpoint or breakpoint location. +/// @class BreakpointOptions BreakpointOptions.h +/// "lldb/Breakpoint/BreakpointOptions.h" +/// @brief Class that manages the options on a breakpoint or breakpoint +/// location. //---------------------------------------------------------------------- -class BreakpointOptions -{ +class BreakpointOptions { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - //------------------------------------------------------------------ - /// Default constructor. The breakpoint is enabled, and has no condition, - /// callback, ignore count, etc... - //------------------------------------------------------------------ - BreakpointOptions(); - BreakpointOptions(const BreakpointOptions& rhs); - - static BreakpointOptions * - CopyOptionsNoCallback (BreakpointOptions &rhs); - //------------------------------------------------------------------ - /// This constructor allows you to specify all the breakpoint options. - /// - /// @param[in] condition - /// The expression which if it evaluates to \b true if we are to stop - /// - /// @param[in] callback - /// This is the plugin for some code that gets run, returns \b true if we are to stop. - /// - /// @param[in] baton - /// Client data that will get passed to the callback. - /// - /// @param[in] enabled - /// Is this breakpoint enabled. - /// - /// @param[in] ignore - /// How many breakpoint hits we should ignore before stopping. - /// - /// @param[in] thread_id - /// Only stop if \a thread_id hits the breakpoint. - //------------------------------------------------------------------ - BreakpointOptions(void *condition, - BreakpointHitCallback callback, - void *baton, - bool enabled = true, - int32_t ignore = 0, - lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID, - bool one_shot = false); - - virtual ~BreakpointOptions(); - - //------------------------------------------------------------------ - // Operators - //------------------------------------------------------------------ - const BreakpointOptions& - operator=(const BreakpointOptions& rhs); - - //------------------------------------------------------------------ - // Callbacks - // - // Breakpoint callbacks come in two forms, synchronous and asynchronous. Synchronous callbacks will get - // run before any of the thread plans are consulted, and if they return false the target will continue - // "under the radar" of the thread plans. There are a couple of restrictions to synchronous callbacks: - // 1) They should NOT resume the target themselves. Just return false if you want the target to restart. - // 2) Breakpoints with synchronous callbacks can't have conditions (or rather, they can have them, but they - // won't do anything. Ditto with ignore counts, etc... You are supposed to control that all through the - // 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. - // The asynchronous callback can run the target itself, but at present that should be the last action the - // callback does. We will relax this condition at some point, but it will take a bit of plumbing to get - // that to work. - // - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Adds a callback to the breakpoint option set. - /// - /// @param[in] callback - /// The function to be called when the breakpoint gets hit. - /// - /// @param[in] baton_sp - /// A baton which will get passed back to the callback when it is invoked. - /// - /// @param[in] synchronous - /// Whether this is a synchronous or asynchronous callback. See discussion above. - //------------------------------------------------------------------ - void SetCallback (BreakpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false); - - //------------------------------------------------------------------ - /// Remove the callback from this option set. - //------------------------------------------------------------------ - void ClearCallback (); - - // The rest of these functions are meant to be used only within the breakpoint handling mechanism. - - //------------------------------------------------------------------ - /// Use this function to invoke the callback for a specific stop. - /// - /// @param[in] context - /// The context in which the callback is to be invoked. This includes the stop event, the - /// execution context of the stop (since you might hit the same breakpoint on multiple threads) and - /// whether we are currently executing synchronous or asynchronous callbacks. - /// - /// @param[in] break_id - /// The breakpoint ID that owns this option set. - /// - /// @param[in] break_loc_id - /// The breakpoint location ID that owns this option set. - /// - /// @return - /// The callback return value. - //------------------------------------------------------------------ - bool InvokeCallback (StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - - //------------------------------------------------------------------ - /// Used in InvokeCallback to tell whether it is the right time to run this kind of callback. - /// - /// @return - /// The synchronicity of our callback. - //------------------------------------------------------------------ - bool IsCallbackSynchronous () const - { - return m_callback_is_synchronous; - } - - //------------------------------------------------------------------ - /// Fetch the baton from the callback. - /// - /// @return - /// The baton. - //------------------------------------------------------------------ - Baton *GetBaton (); - - //------------------------------------------------------------------ - /// Fetch a const version of the baton from the callback. - /// - /// @return - /// The baton. - //------------------------------------------------------------------ - const Baton *GetBaton () const; - - //------------------------------------------------------------------ - // Condition - //------------------------------------------------------------------ - //------------------------------------------------------------------ - /// Set the breakpoint option's condition. - /// - /// @param[in] condition - /// The condition expression to evaluate when the breakpoint is hit. - //------------------------------------------------------------------ - void SetCondition (const char *condition); - - //------------------------------------------------------------------ - /// Return a pointer to the text of the condition expression. - /// - /// @return - /// A pointer to the condition expression text, or nullptr if no - // condition has been set. - //------------------------------------------------------------------ - const char *GetConditionText(size_t *hash = nullptr) const; - - //------------------------------------------------------------------ - // Enabled/Ignore Count - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Check the Enable/Disable state. - /// @return - /// \b true if the breakpoint is enabled, \b false if disabled. - //------------------------------------------------------------------ - bool - IsEnabled () const - { - return m_enabled; - } + struct CommandData { + CommandData() + : user_source(), script_source(), + interpreter(lldb::eScriptLanguageNone), stop_on_error(true) {} - //------------------------------------------------------------------ - /// If \a enable is \b true, enable the breakpoint, if \b false disable it. - //------------------------------------------------------------------ - void - SetEnabled (bool enabled) - { - m_enabled = enabled; - } + CommandData(const StringList &user_source, lldb::ScriptLanguage interp) + : user_source(user_source), script_source(), interpreter(interp), + stop_on_error(true) {} - //------------------------------------------------------------------ - /// Check the One-shot state. - /// @return - /// \b true if the breakpoint is one-shot, \b false otherwise. - //------------------------------------------------------------------ - bool - IsOneShot () const - { - return m_one_shot; - } + ~CommandData() = default; - //------------------------------------------------------------------ - /// If \a enable is \b true, enable the breakpoint, if \b false disable it. - //------------------------------------------------------------------ - void - SetOneShot (bool one_shot) - { - m_one_shot = one_shot; - } + static const char *GetSerializationKey() { return "BKPTCMDData"; } - //------------------------------------------------------------------ - /// Set the breakpoint to ignore the next \a count breakpoint hits. - /// @param[in] count - /// The number of breakpoint hits to ignore. - //------------------------------------------------------------------ + StructuredData::ObjectSP SerializeToStructuredData(); - void - SetIgnoreCount (uint32_t n) - { - m_ignore_count = n; - } + static std::unique_ptr<CommandData> + CreateFromStructuredData(const StructuredData::Dictionary &options_dict, + Error &error); - //------------------------------------------------------------------ - /// Return the current Ignore Count. - /// @return - /// The number of breakpoint hits to be ignored. - //------------------------------------------------------------------ - uint32_t - GetIgnoreCount () const - { - return m_ignore_count; - } + StringList user_source; + std::string script_source; + enum lldb::ScriptLanguage + interpreter; // eScriptLanguageNone means command interpreter. + bool stop_on_error; - //------------------------------------------------------------------ - /// Return the current thread spec for this option. This will return nullptr if the no thread - /// specifications have been set for this Option yet. - /// @return - /// The thread specification pointer for this option, or nullptr if none has - /// been set yet. - //------------------------------------------------------------------ - const ThreadSpec * - GetThreadSpecNoCreate () const; - - //------------------------------------------------------------------ - /// Returns a pointer to the ThreadSpec for this option, creating it. - /// if it hasn't been created already. This API is used for setting the - /// ThreadSpec items for this option. - //------------------------------------------------------------------ - ThreadSpec * - GetThreadSpec (); - - void - SetThreadID(lldb::tid_t thread_id); - - void - GetDescription (Stream *s, lldb::DescriptionLevel level) const; - - //------------------------------------------------------------------ - /// Returns true if the breakpoint option has a callback set. - //------------------------------------------------------------------ - bool - HasCallback() const; - - //------------------------------------------------------------------ - /// This is the default empty callback. - /// @return - /// The thread id for which the breakpoint hit will stop, - /// LLDB_INVALID_THREAD_ID for all threads. - //------------------------------------------------------------------ - static bool - NullCallback (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - struct CommandData - { - CommandData () : - user_source(), - script_source(), - stop_on_error(true) - { - } - - ~CommandData() = default; - - StringList user_source; - std::string script_source; - bool stop_on_error; + private: + enum class OptionNames : uint32_t { + UserSource = 0, + Interpreter, + StopOnError, + LastOptionName }; - class CommandBaton : public Baton - { - public: - CommandBaton (CommandData *data) : - Baton (data) - { - } - - ~CommandBaton() override - { - delete ((CommandData *)m_data); - m_data = nullptr; - } - - void - GetDescription (Stream *s, lldb::DescriptionLevel level) const override; - }; + static const char + *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)]; + + static const char *GetKey(OptionNames enum_value) { + return g_option_names[static_cast<uint32_t>(enum_value)]; + } + }; + + class CommandBaton : public TypedBaton<CommandData> { + public: + explicit CommandBaton(std::unique_ptr<CommandData> Data) + : TypedBaton(std::move(Data)) {} + + void GetDescription(Stream *s, lldb::DescriptionLevel level) const override; + }; + + typedef std::shared_ptr<CommandBaton> CommandBatonSP; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Default constructor. The breakpoint is enabled, and has no condition, + /// callback, ignore count, etc... + //------------------------------------------------------------------ + BreakpointOptions(); + BreakpointOptions(const BreakpointOptions &rhs); + + static BreakpointOptions *CopyOptionsNoCallback(BreakpointOptions &rhs); + + //------------------------------------------------------------------ + /// This constructor allows you to specify all the breakpoint options + /// except the callback. That one is more complicated, and better + /// to do by hand. + /// + /// @param[in] condition + /// The expression which if it evaluates to \b true if we are to stop + /// + /// @param[in] enabled + /// Is this breakpoint enabled. + /// + /// @param[in] ignore + /// How many breakpoint hits we should ignore before stopping. + /// + //------------------------------------------------------------------ + BreakpointOptions(const char *condition, bool enabled = true, + int32_t ignore = 0, bool one_shot = false); + + virtual ~BreakpointOptions(); + + static std::unique_ptr<BreakpointOptions> + CreateFromStructuredData(Target &target, + const StructuredData::Dictionary &data_dict, + Error &error); + + virtual StructuredData::ObjectSP SerializeToStructuredData(); + + static const char *GetSerializationKey() { return "BKPTOptions"; } + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const BreakpointOptions &operator=(const BreakpointOptions &rhs); + + //------------------------------------------------------------------ + // Callbacks + // + // Breakpoint callbacks come in two forms, synchronous and asynchronous. + // Synchronous callbacks will get + // run before any of the thread plans are consulted, and if they return false + // the target will continue + // "under the radar" of the thread plans. There are a couple of restrictions + // to synchronous callbacks: + // 1) They should NOT resume the target themselves. Just return false if you + // want the target to restart. + // 2) Breakpoints with synchronous callbacks can't have conditions (or rather, + // they can have them, but they + // won't do anything. Ditto with ignore counts, etc... You are supposed + // to control that all through the + // 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. + // The asynchronous callback can run the target itself, but at present that + // should be the last action the + // callback does. We will relax this condition at some point, but it will + // take a bit of plumbing to get + // that to work. + // + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Adds a callback to the breakpoint option set. + /// + /// @param[in] callback + /// The function to be called when the breakpoint gets hit. + /// + /// @param[in] baton_sp + /// A baton which will get passed back to the callback when it is invoked. + /// + /// @param[in] synchronous + /// Whether this is a synchronous or asynchronous callback. See discussion + /// above. + //------------------------------------------------------------------ + void SetCallback(BreakpointHitCallback callback, + const lldb::BatonSP &baton_sp, bool synchronous = false); + + void SetCallback(BreakpointHitCallback callback, + const BreakpointOptions::CommandBatonSP &command_baton_sp, + bool synchronous = false); + + //------------------------------------------------------------------ + /// Returns the command line commands for the callback on this breakpoint. + /// + /// @param[out] command_list + /// The commands will be appended to this list. + /// + /// @return + /// \btrue if the command callback is a command-line callback, + /// \bfalse otherwise. + //------------------------------------------------------------------ + bool GetCommandLineCallbacks(StringList &command_list); + + //------------------------------------------------------------------ + /// Remove the callback from this option set. + //------------------------------------------------------------------ + void ClearCallback(); + + // The rest of these functions are meant to be used only within the breakpoint + // handling mechanism. + + //------------------------------------------------------------------ + /// Use this function to invoke the callback for a specific stop. + /// + /// @param[in] context + /// The context in which the callback is to be invoked. This includes the + /// stop event, the + /// execution context of the stop (since you might hit the same breakpoint + /// on multiple threads) and + /// whether we are currently executing synchronous or asynchronous + /// callbacks. + /// + /// @param[in] break_id + /// The breakpoint ID that owns this option set. + /// + /// @param[in] break_loc_id + /// The breakpoint location ID that owns this option set. + /// + /// @return + /// The callback return value. + //------------------------------------------------------------------ + bool InvokeCallback(StoppointCallbackContext *context, + lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Used in InvokeCallback to tell whether it is the right time to run this + /// kind of callback. + /// + /// @return + /// The synchronicity of our callback. + //------------------------------------------------------------------ + bool IsCallbackSynchronous() const { return m_callback_is_synchronous; } + + //------------------------------------------------------------------ + /// Fetch the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + Baton *GetBaton(); + + //------------------------------------------------------------------ + /// Fetch a const version of the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + const Baton *GetBaton() const; + + //------------------------------------------------------------------ + // Condition + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Set the breakpoint option's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the breakpoint is hit. + //------------------------------------------------------------------ + void SetCondition(const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or nullptr if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText(size_t *hash = nullptr) const; + + //------------------------------------------------------------------ + // Enabled/Ignore Count + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Check the Enable/Disable state. + /// @return + /// \b true if the breakpoint is enabled, \b false if disabled. + //------------------------------------------------------------------ + bool IsEnabled() const { return m_enabled; } + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false disable it. + //------------------------------------------------------------------ + void SetEnabled(bool enabled) { m_enabled = enabled; } + + //------------------------------------------------------------------ + /// Check the One-shot state. + /// @return + /// \b true if the breakpoint is one-shot, \b false otherwise. + //------------------------------------------------------------------ + bool IsOneShot() const { return m_one_shot; } + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false disable it. + //------------------------------------------------------------------ + void SetOneShot(bool one_shot) { m_one_shot = one_shot; } + + //------------------------------------------------------------------ + /// Set the breakpoint to ignore the next \a count breakpoint hits. + /// @param[in] count + /// The number of breakpoint hits to ignore. + //------------------------------------------------------------------ + + void SetIgnoreCount(uint32_t n) { m_ignore_count = n; } + + //------------------------------------------------------------------ + /// Return the current Ignore Count. + /// @return + /// The number of breakpoint hits to be ignored. + //------------------------------------------------------------------ + uint32_t GetIgnoreCount() const { return m_ignore_count; } + + //------------------------------------------------------------------ + /// Return the current thread spec for this option. This will return nullptr + /// if the no thread + /// specifications have been set for this Option yet. + /// @return + /// The thread specification pointer for this option, or nullptr if none + /// has + /// been set yet. + //------------------------------------------------------------------ + const ThreadSpec *GetThreadSpecNoCreate() const; + + //------------------------------------------------------------------ + /// Returns a pointer to the ThreadSpec for this option, creating it. + /// if it hasn't been created already. This API is used for setting the + /// ThreadSpec items for this option. + //------------------------------------------------------------------ + ThreadSpec *GetThreadSpec(); + + void SetThreadID(lldb::tid_t thread_id); + + void GetDescription(Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Returns true if the breakpoint option has a callback set. + //------------------------------------------------------------------ + bool HasCallback() const; + + //------------------------------------------------------------------ + /// This is the default empty callback. + //------------------------------------------------------------------ + static bool NullCallback(void *baton, StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Set a callback based on BreakpointOptions::CommandData. + /// @param[in] cmd_data + /// A UP holding the new'ed CommandData object. + /// The breakpoint will take ownership of pointer held by this object. + //------------------------------------------------------------------ + void SetCommandDataCallback(std::unique_ptr<CommandData> &cmd_data); protected: - //------------------------------------------------------------------ - // Classes that inherit from BreakpointOptions can see and modify these - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Classes that inherit from BreakpointOptions can see and modify these + //------------------------------------------------------------------ + enum class OptionNames { + ConditionText = 0, + IgnoreCount, + EnabledState, + OneShotState, + LastOptionName + }; + static const char *g_option_names[(size_t)OptionNames::LastOptionName]; + + static const char *GetKey(OptionNames enum_value) { + return g_option_names[(size_t)enum_value]; + } + + static bool BreakpointOptionsCallbackFunction( + void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + void SetThreadSpec(std::unique_ptr<ThreadSpec> &thread_spec_up); private: - //------------------------------------------------------------------ - // For BreakpointOptions only - //------------------------------------------------------------------ - BreakpointHitCallback m_callback; // This is the callback function pointer - lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback - bool m_callback_is_synchronous; - bool m_enabled; - bool m_one_shot; - uint32_t m_ignore_count; // Number of times to ignore this breakpoint - std::unique_ptr<ThreadSpec> m_thread_spec_ap; // Thread for which this breakpoint will take - std::string m_condition_text; // The condition to test. - size_t m_condition_text_hash; // Its hash, so that locations know when the condition is updated. + //------------------------------------------------------------------ + // For BreakpointOptions only + //------------------------------------------------------------------ + BreakpointHitCallback m_callback; // This is the callback function pointer + lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback + bool m_baton_is_command_baton; + bool m_callback_is_synchronous; + bool m_enabled; + bool m_one_shot; + uint32_t m_ignore_count; // Number of times to ignore this breakpoint + std::unique_ptr<ThreadSpec> + m_thread_spec_ap; // Thread for which this breakpoint will take + std::string m_condition_text; // The condition to test. + size_t m_condition_text_hash; // Its hash, so that locations know when the + // condition is updated. }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h index b117e668a1bd..e19a2135fbd2 100644 --- a/include/lldb/Breakpoint/BreakpointResolver.h +++ b/include/lldb/Breakpoint/BreakpointResolver.h @@ -14,20 +14,22 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Core/Address.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointResolver.h" -#include "lldb/Host/FileSpec.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ConstString.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/SearchFilter.h" -#include "lldb/Core/ConstString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointResolver BreakpointResolver.h "lldb/Breakpoint/BreakpointResolver.h" -/// @brief This class works with SearchFilter to resolve logical breakpoints to their +/// @class BreakpointResolver BreakpointResolver.h +/// "lldb/Breakpoint/BreakpointResolver.h" +/// @brief This class works with SearchFilter to resolve logical breakpoints to +/// their /// of concrete breakpoint locations. //---------------------------------------------------------------------- @@ -35,150 +37,220 @@ namespace lldb_private { /// General Outline: /// The BreakpointResolver is a Searcher. In that protocol, /// the SearchFilter asks the question "At what depth of the symbol context -/// descent do you want your callback to get called?" of the filter. The resolver -/// answers this question (in the GetDepth method) and provides the resolution callback. -/// Each Breakpoint has a BreakpointResolver, and it calls either ResolveBreakpoint -/// or ResolveBreakpointInModules to tell it to look for new breakpoint locations. +/// descent do you want your callback to get called?" of the filter. The +/// resolver +/// answers this question (in the GetDepth method) and provides the resolution +/// callback. +/// Each Breakpoint has a BreakpointResolver, and it calls either +/// ResolveBreakpoint +/// or ResolveBreakpointInModules to tell it to look for new breakpoint +/// locations. //---------------------------------------------------------------------- -class BreakpointResolver : - public Searcher -{ -friend class Breakpoint; +class BreakpointResolver : public Searcher { + friend class Breakpoint; public: - //------------------------------------------------------------------ - /// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint - /// to make sense. It can be constructed without a breakpoint, but you have to - /// call SetBreakpoint before ResolveBreakpoint. - /// - /// @param[in] bkpt - /// The breakpoint that owns this resolver. - /// @param[in] resolverType - /// The concrete breakpoint resolver type for this breakpoint. - /// - /// @result - /// Returns breakpoint location id. - //------------------------------------------------------------------ - BreakpointResolver (Breakpoint *bkpt, unsigned char resolverType, lldb::addr_t offset = 0); - - //------------------------------------------------------------------ - /// The Destructor is virtual, all significant breakpoint resolvers derive - /// from this class. - //------------------------------------------------------------------ - ~BreakpointResolver() override; - - //------------------------------------------------------------------ - /// This sets the breakpoint for this resolver. - /// - /// @param[in] bkpt - /// The breakpoint that owns this resolver. - //------------------------------------------------------------------ - void - SetBreakpoint (Breakpoint *bkpt); - - //------------------------------------------------------------------ - /// This updates the offset for this breakpoint. All the locations currently - /// set for this breakpoint will have their offset adjusted when this is called. - /// - /// @param[in] offset - /// The offset to add to all locations. - //------------------------------------------------------------------ - void - SetOffset (lldb::addr_t offset); - - //------------------------------------------------------------------ - /// This updates the offset for this breakpoint. All the locations currently - /// set for this breakpoint will have their offset adjusted when this is called. - /// - /// @param[in] offset - /// The offset to add to all locations. - //------------------------------------------------------------------ - lldb::addr_t - GetOffset () const - { - return m_offset; - } - - //------------------------------------------------------------------ - /// In response to this method the resolver scans all the modules in the breakpoint's - /// target, and adds any new locations it finds. - /// - /// @param[in] filter - /// The filter that will manage the search for this resolver. - //------------------------------------------------------------------ - virtual void - ResolveBreakpoint (SearchFilter &filter); - - //------------------------------------------------------------------ - /// In response to this method the resolver scans the modules in the module list - /// \a modules, and adds any new locations it finds. - /// - /// @param[in] filter - /// The filter that will manage the search for this resolver. - //------------------------------------------------------------------ - virtual void - ResolveBreakpointInModules (SearchFilter &filter, - ModuleList &modules); - - //------------------------------------------------------------------ - /// Prints a canonical description for the breakpoint to the stream \a s. - /// - /// @param[in] s - /// Stream to which the output is copied. - //------------------------------------------------------------------ - void - GetDescription(Stream *s) override = 0; - - //------------------------------------------------------------------ - /// Standard "Dump" method. At present it does nothing. - //------------------------------------------------------------------ - virtual void - Dump (Stream *s) const = 0; - - //------------------------------------------------------------------ - /// An enumeration for keeping track of the concrete subclass that - /// is actually instantiated. Values of this enumeration are kept in the - /// BreakpointResolver's SubclassID field. They are used for concrete type - /// identification. - enum ResolverTy { - FileLineResolver, // This is an instance of BreakpointResolverFileLine - AddressResolver, // This is an instance of BreakpointResolverAddress - NameResolver, // This is an instance of BreakpointResolverName - FileRegexResolver, - ExceptionResolver, - LastKnownResolverType = ExceptionResolver - }; - - //------------------------------------------------------------------ - /// getResolverID - Return an ID for the concrete type of this object. This - /// is used to implement the LLVM classof checks. This should not be used - /// for any other purpose, as the values may change as LLDB evolves. - unsigned getResolverID() const { - return SubclassID; - } - - virtual lldb::BreakpointResolverSP - CopyForBreakpoint (Breakpoint &breakpoint) = 0; + //------------------------------------------------------------------ + /// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint + /// to make sense. It can be constructed without a breakpoint, but you have + /// to + /// call SetBreakpoint before ResolveBreakpoint. + /// + /// @param[in] bkpt + /// The breakpoint that owns this resolver. + /// @param[in] resolverType + /// The concrete breakpoint resolver type for this breakpoint. + /// + /// @result + /// Returns breakpoint location id. + //------------------------------------------------------------------ + BreakpointResolver(Breakpoint *bkpt, unsigned char resolverType, + lldb::addr_t offset = 0); + + //------------------------------------------------------------------ + /// The Destructor is virtual, all significant breakpoint resolvers derive + /// from this class. + //------------------------------------------------------------------ + ~BreakpointResolver() override; + + //------------------------------------------------------------------ + /// This sets the breakpoint for this resolver. + /// + /// @param[in] bkpt + /// The breakpoint that owns this resolver. + //------------------------------------------------------------------ + void SetBreakpoint(Breakpoint *bkpt); + + //------------------------------------------------------------------ + /// This updates the offset for this breakpoint. All the locations currently + /// set for this breakpoint will have their offset adjusted when this is + /// called. + /// + /// @param[in] offset + /// The offset to add to all locations. + //------------------------------------------------------------------ + void SetOffset(lldb::addr_t offset); + + //------------------------------------------------------------------ + /// This updates the offset for this breakpoint. All the locations currently + /// set for this breakpoint will have their offset adjusted when this is + /// called. + /// + /// @param[in] offset + /// The offset to add to all locations. + //------------------------------------------------------------------ + lldb::addr_t GetOffset() const { return m_offset; } + + //------------------------------------------------------------------ + /// In response to this method the resolver scans all the modules in the + /// breakpoint's + /// target, and adds any new locations it finds. + /// + /// @param[in] filter + /// The filter that will manage the search for this resolver. + //------------------------------------------------------------------ + virtual void ResolveBreakpoint(SearchFilter &filter); + + //------------------------------------------------------------------ + /// In response to this method the resolver scans the modules in the module + /// list + /// \a modules, and adds any new locations it finds. + /// + /// @param[in] filter + /// The filter that will manage the search for this resolver. + //------------------------------------------------------------------ + virtual void ResolveBreakpointInModules(SearchFilter &filter, + ModuleList &modules); + + //------------------------------------------------------------------ + /// Prints a canonical description for the breakpoint to the stream \a s. + /// + /// @param[in] s + /// Stream to which the output is copied. + //------------------------------------------------------------------ + void GetDescription(Stream *s) override = 0; + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + virtual void Dump(Stream *s) const = 0; + + /// This section handles serializing and deserializing from StructuredData + /// objects. + + static lldb::BreakpointResolverSP + CreateFromStructuredData(const StructuredData::Dictionary &resolver_dict, + Error &error); + + virtual StructuredData::ObjectSP SerializeToStructuredData() { + return StructuredData::ObjectSP(); + } + + static const char *GetSerializationKey() { return "BKPTResolver"; } + + static const char *GetSerializationSubclassKey() { return "Type"; } + + static const char *GetSerializationSubclassOptionsKey() { return "Options"; } + + StructuredData::DictionarySP + WrapOptionsDict(StructuredData::DictionarySP options_dict_sp); + + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// An enumeration for keeping track of the concrete subclass that + /// is actually instantiated. Values of this enumeration are kept in the + /// BreakpointResolver's SubclassID field. They are used for concrete type + /// identification. + enum ResolverTy { + FileLineResolver = 0, // This is an instance of BreakpointResolverFileLine + AddressResolver, // This is an instance of BreakpointResolverAddress + NameResolver, // This is an instance of BreakpointResolverName + FileRegexResolver, + ExceptionResolver, + LastKnownResolverType = ExceptionResolver, + UnknownResolver + }; + + // Translate the Ty to name for serialization, + // the "+2" is one for size vrs. index, and one for UnknownResolver. + static const char *g_ty_to_name[LastKnownResolverType + 2]; + + //------------------------------------------------------------------ + /// getResolverID - Return an ID for the concrete type of this object. This + /// is used to implement the LLVM classof checks. This should not be used + /// for any other purpose, as the values may change as LLDB evolves. + unsigned getResolverID() const { return SubclassID; } + + enum ResolverTy GetResolverTy() { + if (SubclassID > ResolverTy::LastKnownResolverType) + return ResolverTy::UnknownResolver; + else + return (enum ResolverTy)SubclassID; + } + + const char *GetResolverName() { return ResolverTyToName(GetResolverTy()); } + + static const char *ResolverTyToName(enum ResolverTy); + + static ResolverTy NameToResolverTy(const char *name); + + virtual lldb::BreakpointResolverSP + CopyForBreakpoint(Breakpoint &breakpoint) = 0; protected: - //------------------------------------------------------------------ - /// SetSCMatchesByLine - Takes a symbol context list of matches which supposedly represent the same file and - /// line number in a CU, and find the nearest actual line number that matches, and then filter down the - /// matching addresses to unique entries, and skip the prologue if asked to do so, and then set - /// breakpoint locations in this breakpoint for all the resultant addresses. - void SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident); - - lldb::BreakpointLocationSP - AddLocation(Address loc_addr, bool *new_location = NULL); - - Breakpoint *m_breakpoint; // This is the breakpoint we add locations to. - lldb::addr_t m_offset; // A random offset the user asked us to add to any breakpoints we set. + // Used for serializing resolver options: + // The options in this enum and the strings in the + // g_option_names must be kept in sync. + enum class OptionNames : uint32_t { + AddressOffset = 0, + ExactMatch, + FileName, + Inlines, + LanguageName, + LineNumber, + ModuleName, + NameMaskArray, + Offset, + RegexString, + SectionName, + SkipPrologue, + SymbolNameArray, + LastOptionName + }; + static const char + *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)]; + +public: + static const char *GetKey(OptionNames enum_value) { + return g_option_names[static_cast<uint32_t>(enum_value)]; + } + +protected: + //------------------------------------------------------------------ + /// SetSCMatchesByLine - Takes a symbol context list of matches which + /// supposedly represent the same file and + /// line number in a CU, and find the nearest actual line number that matches, + /// and then filter down the + /// matching addresses to unique entries, and skip the prologue if asked to do + /// so, and then set + /// breakpoint locations in this breakpoint for all the resultant addresses. + void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list, + bool skip_prologue, llvm::StringRef log_ident); + void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool, + const char *) = delete; + + lldb::BreakpointLocationSP AddLocation(Address loc_addr, + bool *new_location = NULL); + + Breakpoint *m_breakpoint; // This is the breakpoint we add locations to. + lldb::addr_t m_offset; // A random offset the user asked us to add to any + // breakpoints we set. private: - // Subclass identifier (for llvm isa/dyn_cast) - const unsigned char SubclassID; - DISALLOW_COPY_AND_ASSIGN(BreakpointResolver); + // Subclass identifier (for llvm isa/dyn_cast) + const unsigned char SubclassID; + DISALLOW_COPY_AND_ASSIGN(BreakpointResolver); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointResolverAddress.h b/include/lldb/Breakpoint/BreakpointResolverAddress.h index 8ec1e39e52ab..6d2d505811f9 100644 --- a/include/lldb/Breakpoint/BreakpointResolverAddress.h +++ b/include/lldb/Breakpoint/BreakpointResolverAddress.h @@ -20,63 +20,64 @@ namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointResolverAddress BreakpointResolverAddress.h "lldb/Breakpoint/BreakpointResolverAddress.h" -/// @brief This class sets breakpoints on a given Address. This breakpoint only takes +/// @class BreakpointResolverAddress BreakpointResolverAddress.h +/// "lldb/Breakpoint/BreakpointResolverAddress.h" +/// @brief This class sets breakpoints on a given Address. This breakpoint only +/// takes /// once, and then it won't attempt to reset itself. //---------------------------------------------------------------------- -class BreakpointResolverAddress: - public BreakpointResolver -{ +class BreakpointResolverAddress : public BreakpointResolver { public: - BreakpointResolverAddress (Breakpoint *bkpt, - const Address &addr); + BreakpointResolverAddress(Breakpoint *bkpt, const Address &addr); - BreakpointResolverAddress (Breakpoint *bkpt, - const Address &addr, - const FileSpec &module_spec); + BreakpointResolverAddress(Breakpoint *bkpt, const Address &addr, + const FileSpec &module_spec); - ~BreakpointResolverAddress() override; + ~BreakpointResolverAddress() override; - void - ResolveBreakpoint (SearchFilter &filter) override; + static BreakpointResolver * + CreateFromStructuredData(Breakpoint *bkpt, + const StructuredData::Dictionary &options_dict, + Error &error); - void - ResolveBreakpointInModules (SearchFilter &filter, - ModuleList &modules) override; + StructuredData::ObjectSP SerializeToStructuredData() override; - Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing) override; + void ResolveBreakpoint(SearchFilter &filter) override; - Searcher::Depth - GetDepth () override; + void ResolveBreakpointInModules(SearchFilter &filter, + ModuleList &modules) override; - void - GetDescription (Stream *s) override; + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, Address *addr, + bool containing) override; - void - Dump (Stream *s) const override; + Searcher::Depth GetDepth() override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BreakpointResolverAddress *) { return true; } - static inline bool classof(const BreakpointResolver *V) { - return V->getResolverID() == BreakpointResolver::AddressResolver; - } + void GetDescription(Stream *s) override; - lldb::BreakpointResolverSP - CopyForBreakpoint (Breakpoint &breakpoint) override; + void Dump(Stream *s) const override; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverAddress *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::AddressResolver; + } + + lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override; protected: - Address m_addr; // The address - may be Section Offset or may be just an offset - lldb::addr_t m_resolved_addr; // The current value of the resolved load address for this breakpoint, - FileSpec m_module_filespec; // If this filespec is Valid, and m_addr is an offset, then it will be converted - // to a Section+Offset address in this module, whenever that module gets around to - // being loaded. + Address + m_addr; // The address - may be Section Offset or may be just an offset + lldb::addr_t m_resolved_addr; // The current value of the resolved load + // address for this breakpoint, + FileSpec m_module_filespec; // If this filespec is Valid, and m_addr is an + // offset, then it will be converted + // to a Section+Offset address in this module, whenever that module gets + // around to + // being loaded. private: - DISALLOW_COPY_AND_ASSIGN(BreakpointResolverAddress); + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverAddress); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h index cea192b5edbf..f1fdf60e74ec 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -19,59 +19,60 @@ namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointResolverFileLine BreakpointResolverFileLine.h "lldb/Breakpoint/BreakpointResolverFileLine.h" -/// @brief This class sets breakpoints by file and line. Optionally, it will look for inlined +/// @class BreakpointResolverFileLine BreakpointResolverFileLine.h +/// "lldb/Breakpoint/BreakpointResolverFileLine.h" +/// @brief This class sets breakpoints by file and line. Optionally, it will +/// look for inlined /// instances of the file and line specification. //---------------------------------------------------------------------- -class BreakpointResolverFileLine : - public BreakpointResolver -{ +class BreakpointResolverFileLine : public BreakpointResolver { public: - BreakpointResolverFileLine (Breakpoint *bkpt, - const FileSpec &resolver, - uint32_t line_no, - lldb::addr_t m_offset, - bool check_inlines, - bool skip_prologue, - bool exact_match); + BreakpointResolverFileLine(Breakpoint *bkpt, const FileSpec &resolver, + uint32_t line_no, lldb::addr_t m_offset, + bool check_inlines, bool skip_prologue, + bool exact_match); - ~BreakpointResolverFileLine() override; + static BreakpointResolver * + CreateFromStructuredData(Breakpoint *bkpt, + const StructuredData::Dictionary &data_dict, + Error &error); - Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing) override; + StructuredData::ObjectSP SerializeToStructuredData() override; - Searcher::Depth - GetDepth () override; + ~BreakpointResolverFileLine() override; - void - GetDescription (Stream *s) override; + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, Address *addr, + bool containing) override; - void - Dump (Stream *s) const override; + Searcher::Depth GetDepth() override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BreakpointResolverFileLine *) { return true; } - static inline bool classof(const BreakpointResolver *V) { - return V->getResolverID() == BreakpointResolver::FileLineResolver; - } + void GetDescription(Stream *s) override; - lldb::BreakpointResolverSP - CopyForBreakpoint (Breakpoint &breakpoint) override; + void Dump(Stream *s) const override; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverFileLine *) { + return true; + } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::FileLineResolver; + } + + lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override; protected: - friend class Breakpoint; - FileSpec m_file_spec; // This is the file spec we are looking for. - uint32_t m_line_number; // This is the line number that we are looking for. - bool m_inlines; // This determines whether the resolver looks for inlined functions or not. - bool m_skip_prologue; - bool m_exact_match; + friend class Breakpoint; + FileSpec m_file_spec; // This is the file spec we are looking for. + uint32_t m_line_number; // This is the line number that we are looking for. + bool m_inlines; // This determines whether the resolver looks for inlined + // functions or not. + bool m_skip_prologue; + bool m_exact_match; private: - DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileLine); + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileLine); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h index ce67c2dc98ec..0429e264774e 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -1,4 +1,5 @@ -//===-- BreakpointResolverFileRegex.h ----------------------------*- C++ -*-===// +//===-- BreakpointResolverFileRegex.h ----------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -21,57 +22,62 @@ namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointResolverFileRegex BreakpointResolverFileRegex.h "lldb/Breakpoint/BreakpointResolverFileRegex.h" -/// @brief This class sets breakpoints by file and line. Optionally, it will look for inlined +/// @class BreakpointResolverFileRegex BreakpointResolverFileRegex.h +/// "lldb/Breakpoint/BreakpointResolverFileRegex.h" +/// @brief This class sets breakpoints by file and line. Optionally, it will +/// look for inlined /// instances of the file and line specification. //---------------------------------------------------------------------- -class BreakpointResolverFileRegex : - public BreakpointResolver -{ +class BreakpointResolverFileRegex : public BreakpointResolver { public: - BreakpointResolverFileRegex (Breakpoint *bkpt, - RegularExpression ®ex, - const std::unordered_set<std::string> &func_name_set, - bool exact_match); + BreakpointResolverFileRegex( + Breakpoint *bkpt, RegularExpression ®ex, + const std::unordered_set<std::string> &func_name_set, bool exact_match); - ~BreakpointResolverFileRegex() override; + static BreakpointResolver * + CreateFromStructuredData(Breakpoint *bkpt, + const StructuredData::Dictionary &options_dict, + Error &error); - Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing) override; + StructuredData::ObjectSP SerializeToStructuredData() override; - Searcher::Depth - GetDepth () override; + ~BreakpointResolverFileRegex() override; - void - GetDescription (Stream *s) override; + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, Address *addr, + bool containing) override; - void - Dump (Stream *s) const override; - - void - AddFunctionName(const char *func_name); + Searcher::Depth GetDepth() override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BreakpointResolverFileRegex *) { return true; } - static inline bool classof(const BreakpointResolver *V) { - return V->getResolverID() == BreakpointResolver::FileRegexResolver; - } + void GetDescription(Stream *s) override; - lldb::BreakpointResolverSP - CopyForBreakpoint (Breakpoint &breakpoint) override; + void Dump(Stream *s) const override; + + void AddFunctionName(const char *func_name); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverFileRegex *) { + return true; + } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::FileRegexResolver; + } + + lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override; protected: - friend class Breakpoint; - RegularExpression m_regex; // This is the line expression that we are looking for. - bool m_exact_match; // If true, then if the source we match is in a comment, we won't set a location there. - std::unordered_set<std::string> m_function_names; // Limit the search to functions in the comp_unit passed in. + friend class Breakpoint; + RegularExpression + m_regex; // This is the line expression that we are looking for. + bool m_exact_match; // If true, then if the source we match is in a comment, + // we won't set a location there. + std::unordered_set<std::string> m_function_names; // Limit the search to + // functions in the + // comp_unit passed in. private: - DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex); + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointResolverName.h b/include/lldb/Breakpoint/BreakpointResolverName.h index a11359dd0094..4223125d9268 100644 --- a/include/lldb/Breakpoint/BreakpointResolverName.h +++ b/include/lldb/Breakpoint/BreakpointResolverName.h @@ -12,8 +12,8 @@ // C Includes // C++ Includes -#include <vector> #include <string> +#include <vector> // Other libraries and framework includes // Project includes @@ -23,93 +23,75 @@ namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointResolverName BreakpointResolverName.h "lldb/Breakpoint/BreakpointResolverName.h" -/// @brief This class sets breakpoints on a given function name, either by exact match +/// @class BreakpointResolverName BreakpointResolverName.h +/// "lldb/Breakpoint/BreakpointResolverName.h" +/// @brief This class sets breakpoints on a given function name, either by exact +/// match /// or by regular expression. //---------------------------------------------------------------------- -class BreakpointResolverName: - public BreakpointResolver -{ +class BreakpointResolverName : public BreakpointResolver { public: + BreakpointResolverName(Breakpoint *bkpt, const char *name, + uint32_t name_type_mask, lldb::LanguageType language, + Breakpoint::MatchType type, lldb::addr_t offset, + bool skip_prologue); + + // This one takes an array of names. It is always MatchType = Exact. + BreakpointResolverName(Breakpoint *bkpt, const char *names[], + size_t num_names, uint32_t name_type_mask, + lldb::LanguageType language, lldb::addr_t offset, + bool skip_prologue); + + // This one takes a C++ array of names. It is always MatchType = Exact. + BreakpointResolverName(Breakpoint *bkpt, std::vector<std::string> names, + uint32_t name_type_mask, lldb::LanguageType language, + lldb::addr_t offset, bool skip_prologue); + + // Creates a function breakpoint by regular expression. Takes over control of + // the lifespan of func_regex. + BreakpointResolverName(Breakpoint *bkpt, RegularExpression &func_regex, + lldb::LanguageType language, lldb::addr_t offset, + bool skip_prologue); + + static BreakpointResolver * + CreateFromStructuredData(Breakpoint *bkpt, + const StructuredData::Dictionary &data_dict, + Error &error); + + StructuredData::ObjectSP SerializeToStructuredData() override; + + ~BreakpointResolverName() override; + + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, Address *addr, + bool containing) override; + + Searcher::Depth GetDepth() override; + + void GetDescription(Stream *s) override; + + void Dump(Stream *s) const override; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverName *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::NameResolver; + } - BreakpointResolverName (Breakpoint *bkpt, - const char *name, - uint32_t name_type_mask, - lldb::LanguageType language, - Breakpoint::MatchType type, - lldb::addr_t offset, - bool skip_prologue); - - // This one takes an array of names. It is always MatchType = Exact. - BreakpointResolverName (Breakpoint *bkpt, - const char *names[], - size_t num_names, - uint32_t name_type_mask, - lldb::LanguageType language, - lldb::addr_t offset, - bool skip_prologue); - - // This one takes a C++ array of names. It is always MatchType = Exact. - BreakpointResolverName (Breakpoint *bkpt, - std::vector<std::string> names, - uint32_t name_type_mask, - lldb::LanguageType language, - lldb::addr_t offset, - bool skip_prologue); - - // Creates a function breakpoint by regular expression. Takes over control of the lifespan of func_regex. - BreakpointResolverName (Breakpoint *bkpt, - RegularExpression &func_regex, - lldb::LanguageType language, - lldb::addr_t offset, - bool skip_prologue); - - BreakpointResolverName (Breakpoint *bkpt, - const char *class_name, - const char *method, - Breakpoint::MatchType type, - lldb::addr_t offset, - bool skip_prologue); - - ~BreakpointResolverName() override; - - Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing) override; - - Searcher::Depth - GetDepth () override; - - void - GetDescription (Stream *s) override; - - void - Dump (Stream *s) const override; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const BreakpointResolverName *) { return true; } - static inline bool classof(const BreakpointResolver *V) { - return V->getResolverID() == BreakpointResolver::NameResolver; - } - - lldb::BreakpointResolverSP - CopyForBreakpoint (Breakpoint &breakpoint) override; + lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override; protected: - BreakpointResolverName(const BreakpointResolverName &rhs); + BreakpointResolverName(const BreakpointResolverName &rhs); - std::vector<Module::LookupInfo> m_lookups; - ConstString m_class_name; - RegularExpression m_regex; - Breakpoint::MatchType m_match_type; - lldb::LanguageType m_language; - bool m_skip_prologue; + std::vector<Module::LookupInfo> m_lookups; + ConstString m_class_name; + RegularExpression m_regex; + Breakpoint::MatchType m_match_type; + lldb::LanguageType m_language; + bool m_skip_prologue; - void - AddNameLookup (const ConstString &name, uint32_t name_type_mask); + void AddNameLookup(const ConstString &name, uint32_t name_type_mask); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointSite.h b/include/lldb/Breakpoint/BreakpointSite.h index 27a23527d9fa..b334c6e1a276 100644 --- a/include/lldb/Breakpoint/BreakpointSite.h +++ b/include/lldb/Breakpoint/BreakpointSite.h @@ -19,10 +19,10 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-forward.h" -#include "lldb/Core/UserID.h" -#include "lldb/Breakpoint/StoppointLocation.h" #include "lldb/Breakpoint/BreakpointLocationCollection.h" +#include "lldb/Breakpoint/StoppointLocation.h" +#include "lldb/Core/UserID.h" +#include "lldb/lldb-forward.h" namespace lldb_private { @@ -39,277 +39,247 @@ namespace lldb_private { /// site. Breakpoint sites are owned by the process. //---------------------------------------------------------------------- -class BreakpointSite : - public std::enable_shared_from_this<BreakpointSite>, - public StoppointLocation -{ +class BreakpointSite : public std::enable_shared_from_this<BreakpointSite>, + public StoppointLocation { public: - - enum Type - { - eSoftware, // Breakpoint opcode has been written to memory and m_saved_opcode - // and m_trap_opcode contain the saved and written opcode. - eHardware, // Breakpoint site is set as a hardware breakpoint - eExternal // Breakpoint site is managed by an external debug nub or - // debug interface where memory reads transparently will not - // display any breakpoint opcodes. - }; - - ~BreakpointSite() override; - - //---------------------------------------------------------------------- - // This section manages the breakpoint traps - //---------------------------------------------------------------------- - - //------------------------------------------------------------------ - /// Returns the Opcode Bytes for this breakpoint - //------------------------------------------------------------------ - uint8_t * - GetTrapOpcodeBytes (); - - //------------------------------------------------------------------ - /// Returns the Opcode Bytes for this breakpoint - const version - //------------------------------------------------------------------ - const uint8_t * - GetTrapOpcodeBytes () const; - - //------------------------------------------------------------------ - /// Get the size of the trap opcode for this address - //------------------------------------------------------------------ - size_t - GetTrapOpcodeMaxByteSize () const; - - //------------------------------------------------------------------ - /// Sets the trap opcode - //------------------------------------------------------------------ - bool - SetTrapOpcode (const uint8_t *trap_opcode, - uint32_t trap_opcode_size); - - //------------------------------------------------------------------ - /// Gets the original instruction bytes that were overwritten by the trap - //------------------------------------------------------------------ - uint8_t * - GetSavedOpcodeBytes (); - - //------------------------------------------------------------------ - /// Gets the original instruction bytes that were overwritten by the trap const version - //------------------------------------------------------------------ - const uint8_t * - GetSavedOpcodeBytes () const; - - //------------------------------------------------------------------ - /// Says whether \a addr and size \a size intersects with the address \a intersect_addr - //------------------------------------------------------------------ - bool - IntersectsRange (lldb::addr_t addr, - size_t size, - lldb::addr_t *intersect_addr, - size_t *intersect_size, - size_t *opcode_offset) const; - - //------------------------------------------------------------------ - /// Tells whether the current breakpoint site is enabled or not - /// - /// This is a low-level enable bit for the breakpoint sites. If a - /// breakpoint site has no enabled owners, it should just get - /// removed. This enable/disable is for the low-level target code - /// to enable and disable breakpoint sites when single stepping, - /// etc. - //------------------------------------------------------------------ - bool - IsEnabled () const; - - //------------------------------------------------------------------ - /// Sets whether the current breakpoint site is enabled or not - /// - /// @param[in] enabled - /// \b true if the breakpoint is enabled, \b false otherwise. - //------------------------------------------------------------------ - void - SetEnabled (bool enabled); - - //------------------------------------------------------------------ - /// Enquires of the breakpoint locations that produced this breakpoint site whether - /// we should stop at this location. - /// - /// @param[in] context - /// This contains the information about this stop. - /// - /// @return - /// \b true if we should stop, \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldStop(StoppointCallbackContext *context) override; - - //------------------------------------------------------------------ - /// Standard Dump method - /// - /// @param[in] context - /// The stream to dump this output. - //------------------------------------------------------------------ - void - Dump(Stream *s) const override; - - //------------------------------------------------------------------ - /// The "Owners" are the breakpoint locations that share this - /// breakpoint site. The method adds the \a owner to this breakpoint - /// site's owner list. - /// - /// @param[in] context - /// \a owner is the Breakpoint Location to add. - //------------------------------------------------------------------ - void - AddOwner (const lldb::BreakpointLocationSP &owner); - - //------------------------------------------------------------------ - /// This method returns the number of breakpoint locations currently - /// located at this breakpoint site. - /// - /// @return - /// The number of owners. - //------------------------------------------------------------------ - size_t - GetNumberOfOwners (); - - //------------------------------------------------------------------ - /// This method returns the breakpoint location at index \a index - /// located at this breakpoint site. The owners are listed ordinally - /// from 0 to GetNumberOfOwners() - 1 so you can use this method to iterate - /// over the owners - /// - /// @param[in] index - /// The index in the list of owners for which you wish the owner location. - /// @return - /// A shared pointer to the breakpoint location at that index. - //------------------------------------------------------------------ - lldb::BreakpointLocationSP - GetOwnerAtIndex (size_t idx); - - //------------------------------------------------------------------ - /// This method copies the breakpoint site's owners into a new collection. - /// It does this while the owners mutex is locked. - /// - /// @param[out] out_collection - /// The BreakpointLocationCollection into which to put the owners - /// of this breakpoint site. - /// - /// @return - /// The number of elements copied into out_collection. - //------------------------------------------------------------------ - size_t - CopyOwnersList (BreakpointLocationCollection &out_collection); - - //------------------------------------------------------------------ - /// Check whether the owners of this breakpoint site have any - /// thread specifiers, and if yes, is \a thread contained in any - /// of these specifiers. - /// - /// @param[in] thread - /// The thread against which to test. - /// - /// return - /// \b true if the collection contains at least one location that - /// would be valid for this thread, false otherwise. - //------------------------------------------------------------------ - bool - ValidForThisThread (Thread *thread); - - //------------------------------------------------------------------ - /// Print a description of this breakpoint site to the stream \a s. - /// GetDescription tells you about the breakpoint site's owners. - /// Use BreakpointSite::Dump(Stream *) to get information about the - /// breakpoint site itself. - /// - /// @param[in] s - /// The stream to which to print the description. - /// - /// @param[in] level - /// The description level that indicates the detail level to - /// provide. - /// - /// @see lldb::DescriptionLevel - //------------------------------------------------------------------ - void - GetDescription (Stream *s, - lldb::DescriptionLevel level); - - //------------------------------------------------------------------ - /// Tell whether a breakpoint has a location at this site. - /// - /// @param[in] bp_id - /// The breakpoint id to query. - /// - /// @result - /// \b true if bp_id has a location that is at this site, - /// \b false otherwise. - //------------------------------------------------------------------ - bool - IsBreakpointAtThisSite (lldb::break_id_t bp_id); - - //------------------------------------------------------------------ - /// Tell whether ALL the breakpoints in the location collection are internal. - /// - /// @result - /// \b true if all breakpoint locations are owned by internal breakpoints, - /// \b false otherwise. - //------------------------------------------------------------------ - bool - IsInternal () const; - - BreakpointSite::Type - GetType () const - { - return m_type; - } - - void - SetType (BreakpointSite::Type type) - { - m_type = type; - } + enum Type { + eSoftware, // Breakpoint opcode has been written to memory and + // m_saved_opcode + // and m_trap_opcode contain the saved and written opcode. + eHardware, // Breakpoint site is set as a hardware breakpoint + eExternal // Breakpoint site is managed by an external debug nub or + // debug interface where memory reads transparently will not + // display any breakpoint opcodes. + }; + + ~BreakpointSite() override; + + //---------------------------------------------------------------------- + // This section manages the breakpoint traps + //---------------------------------------------------------------------- + + //------------------------------------------------------------------ + /// Returns the Opcode Bytes for this breakpoint + //------------------------------------------------------------------ + uint8_t *GetTrapOpcodeBytes(); + + //------------------------------------------------------------------ + /// Returns the Opcode Bytes for this breakpoint - const version + //------------------------------------------------------------------ + const uint8_t *GetTrapOpcodeBytes() const; + + //------------------------------------------------------------------ + /// Get the size of the trap opcode for this address + //------------------------------------------------------------------ + size_t GetTrapOpcodeMaxByteSize() const; + + //------------------------------------------------------------------ + /// Sets the trap opcode + //------------------------------------------------------------------ + bool SetTrapOpcode(const uint8_t *trap_opcode, uint32_t trap_opcode_size); + + //------------------------------------------------------------------ + /// Gets the original instruction bytes that were overwritten by the trap + //------------------------------------------------------------------ + uint8_t *GetSavedOpcodeBytes(); + + //------------------------------------------------------------------ + /// Gets the original instruction bytes that were overwritten by the trap + /// const version + //------------------------------------------------------------------ + const uint8_t *GetSavedOpcodeBytes() const; + + //------------------------------------------------------------------ + /// Says whether \a addr and size \a size intersects with the address \a + /// intersect_addr + //------------------------------------------------------------------ + bool IntersectsRange(lldb::addr_t addr, size_t size, + lldb::addr_t *intersect_addr, size_t *intersect_size, + size_t *opcode_offset) const; + + //------------------------------------------------------------------ + /// Tells whether the current breakpoint site is enabled or not + /// + /// This is a low-level enable bit for the breakpoint sites. If a + /// breakpoint site has no enabled owners, it should just get + /// removed. This enable/disable is for the low-level target code + /// to enable and disable breakpoint sites when single stepping, + /// etc. + //------------------------------------------------------------------ + bool IsEnabled() const; + + //------------------------------------------------------------------ + /// Sets whether the current breakpoint site is enabled or not + /// + /// @param[in] enabled + /// \b true if the breakpoint is enabled, \b false otherwise. + //------------------------------------------------------------------ + void SetEnabled(bool enabled); + + //------------------------------------------------------------------ + /// Enquires of the breakpoint locations that produced this breakpoint site + /// whether + /// we should stop at this location. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool ShouldStop(StoppointCallbackContext *context) override; + + //------------------------------------------------------------------ + /// Standard Dump method + /// + /// @param[in] context + /// The stream to dump this output. + //------------------------------------------------------------------ + void Dump(Stream *s) const override; + + //------------------------------------------------------------------ + /// The "Owners" are the breakpoint locations that share this + /// breakpoint site. The method adds the \a owner to this breakpoint + /// site's owner list. + /// + /// @param[in] context + /// \a owner is the Breakpoint Location to add. + //------------------------------------------------------------------ + void AddOwner(const lldb::BreakpointLocationSP &owner); + + //------------------------------------------------------------------ + /// This method returns the number of breakpoint locations currently + /// located at this breakpoint site. + /// + /// @return + /// The number of owners. + //------------------------------------------------------------------ + size_t GetNumberOfOwners(); + + //------------------------------------------------------------------ + /// This method returns the breakpoint location at index \a index + /// located at this breakpoint site. The owners are listed ordinally + /// from 0 to GetNumberOfOwners() - 1 so you can use this method to iterate + /// over the owners + /// + /// @param[in] index + /// The index in the list of owners for which you wish the owner location. + /// @return + /// A shared pointer to the breakpoint location at that index. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP GetOwnerAtIndex(size_t idx); + + //------------------------------------------------------------------ + /// This method copies the breakpoint site's owners into a new collection. + /// It does this while the owners mutex is locked. + /// + /// @param[out] out_collection + /// The BreakpointLocationCollection into which to put the owners + /// of this breakpoint site. + /// + /// @return + /// The number of elements copied into out_collection. + //------------------------------------------------------------------ + size_t CopyOwnersList(BreakpointLocationCollection &out_collection); + + //------------------------------------------------------------------ + /// Check whether the owners of this breakpoint site have any + /// thread specifiers, and if yes, is \a thread contained in any + /// of these specifiers. + /// + /// @param[in] thread + /// The thread against which to test. + /// + /// return + /// \b true if the collection contains at least one location that + /// would be valid for this thread, false otherwise. + //------------------------------------------------------------------ + bool ValidForThisThread(Thread *thread); + + //------------------------------------------------------------------ + /// Print a description of this breakpoint site to the stream \a s. + /// GetDescription tells you about the breakpoint site's owners. + /// Use BreakpointSite::Dump(Stream *) to get information about the + /// breakpoint site itself. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription(Stream *s, lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Tell whether a breakpoint has a location at this site. + /// + /// @param[in] bp_id + /// The breakpoint id to query. + /// + /// @result + /// \b true if bp_id has a location that is at this site, + /// \b false otherwise. + //------------------------------------------------------------------ + bool IsBreakpointAtThisSite(lldb::break_id_t bp_id); + + //------------------------------------------------------------------ + /// Tell whether ALL the breakpoints in the location collection are internal. + /// + /// @result + /// \b true if all breakpoint locations are owned by internal breakpoints, + /// \b false otherwise. + //------------------------------------------------------------------ + bool IsInternal() const; + + BreakpointSite::Type GetType() const { return m_type; } + + void SetType(BreakpointSite::Type type) { m_type = type; } private: - friend class Process; - friend class BreakpointLocation; - // The StopInfoBreakpoint knows when it is processing a hit for a thread for a site, so let it be the - // one to manage setting the location hit count once and only once. - friend class StopInfoBreakpoint; - - void - BumpHitCounts(); - - //------------------------------------------------------------------ - /// The method removes the owner at \a break_loc_id from this breakpoint list. - /// - /// @param[in] context - /// \a break_loc_id is the Breakpoint Location to remove. - //------------------------------------------------------------------ - size_t - RemoveOwner (lldb::break_id_t break_id, - lldb::break_id_t break_loc_id); - - BreakpointSite::Type m_type;///< The type of this breakpoint site. - uint8_t m_saved_opcode[8]; ///< The saved opcode bytes if this breakpoint site uses trap opcodes. - uint8_t m_trap_opcode[8]; ///< The opcode that was used to create the breakpoint if it is a software breakpoint site. - bool m_enabled; ///< Boolean indicating if this breakpoint site enabled or not. - - // Consider adding an optimization where if there is only one - // owner, we don't store a list. The usual case will be only one owner... - BreakpointLocationCollection m_owners; ///< This has the BreakpointLocations that share this breakpoint site. - std::recursive_mutex m_owners_mutex; ///< This mutex protects the owners collection. - - static lldb::break_id_t - GetNextID(); - - // Only the Process can create breakpoint sites in - // Process::CreateBreakpointSite (lldb::BreakpointLocationSP &, bool). - BreakpointSite (BreakpointSiteList *list, - const lldb::BreakpointLocationSP& owner, - lldb::addr_t m_addr, - bool use_hardware); - - DISALLOW_COPY_AND_ASSIGN(BreakpointSite); + friend class Process; + friend class BreakpointLocation; + // The StopInfoBreakpoint knows when it is processing a hit for a thread for a + // site, so let it be the + // one to manage setting the location hit count once and only once. + friend class StopInfoBreakpoint; + + void BumpHitCounts(); + + //------------------------------------------------------------------ + /// The method removes the owner at \a break_loc_id from this breakpoint list. + /// + /// @param[in] context + /// \a break_loc_id is the Breakpoint Location to remove. + //------------------------------------------------------------------ + size_t RemoveOwner(lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + + BreakpointSite::Type m_type; ///< The type of this breakpoint site. + uint8_t m_saved_opcode[8]; ///< The saved opcode bytes if this breakpoint site + ///uses trap opcodes. + uint8_t m_trap_opcode[8]; ///< The opcode that was used to create the + ///breakpoint if it is a software breakpoint site. + bool + m_enabled; ///< Boolean indicating if this breakpoint site enabled or not. + + // Consider adding an optimization where if there is only one + // owner, we don't store a list. The usual case will be only one owner... + BreakpointLocationCollection m_owners; ///< This has the BreakpointLocations + ///that share this breakpoint site. + std::recursive_mutex + m_owners_mutex; ///< This mutex protects the owners collection. + + static lldb::break_id_t GetNextID(); + + // Only the Process can create breakpoint sites in + // Process::CreateBreakpointSite (lldb::BreakpointLocationSP &, bool). + BreakpointSite(BreakpointSiteList *list, + const lldb::BreakpointLocationSP &owner, lldb::addr_t m_addr, + bool use_hardware); + + DISALLOW_COPY_AND_ASSIGN(BreakpointSite); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointSiteList.h b/include/lldb/Breakpoint/BreakpointSiteList.h index e681aa3599f7..1431fe799675 100644 --- a/include/lldb/Breakpoint/BreakpointSiteList.h +++ b/include/lldb/Breakpoint/BreakpointSiteList.h @@ -23,197 +23,185 @@ namespace lldb_private { //---------------------------------------------------------------------- -/// @class BreakpointSiteList BreakpointSiteList.h "lldb/Breakpoint/BreakpointSiteList.h" +/// @class BreakpointSiteList BreakpointSiteList.h +/// "lldb/Breakpoint/BreakpointSiteList.h" /// @brief Class that manages lists of BreakpointSite shared pointers. //---------------------------------------------------------------------- -class BreakpointSiteList -{ -// At present Process directly accesses the map of BreakpointSites so it can -// do quick lookups into the map (using GetMap). -// FIXME: Find a better interface for this. -friend class Process; +class BreakpointSiteList { + // At present Process directly accesses the map of BreakpointSites so it can + // do quick lookups into the map (using GetMap). + // FIXME: Find a better interface for this. + friend class Process; public: - //------------------------------------------------------------------ - /// Default constructor makes an empty list. - //------------------------------------------------------------------ - BreakpointSiteList(); - - //------------------------------------------------------------------ - /// Destructor, currently does nothing. - //------------------------------------------------------------------ - ~BreakpointSiteList(); - - //------------------------------------------------------------------ - /// Add a BreakpointSite to the list. - /// - /// @param[in] bp_site_sp - /// A shared pointer to a breakpoint site being added to the list. - /// - /// @return - /// The ID of the BreakpointSite in the list. - //------------------------------------------------------------------ - lldb::break_id_t - Add (const lldb::BreakpointSiteSP& bp_site_sp); - - //------------------------------------------------------------------ - /// Standard Dump routine, doesn't do anything at present. - /// @param[in] s - /// Stream into which to dump the description. - //------------------------------------------------------------------ - void - Dump (Stream *s) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint site at address - /// \a addr. - /// - /// @param[in] addr - /// The address to look for. - /// - /// @result - /// A shared pointer to the breakpoint site. May contain a NULL - /// pointer if no breakpoint site exists with a matching address. - //------------------------------------------------------------------ - lldb::BreakpointSiteSP - FindByAddress (lldb::addr_t addr); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint site with id \a breakID. - /// - /// @param[in] breakID - /// The breakpoint site ID to seek for. - /// - /// @result - /// A shared pointer to the breakpoint site. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointSiteSP - FindByID (lldb::break_id_t breakID); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint site with id \a breakID - const version. - /// - /// @param[in] breakID - /// The breakpoint site ID to seek for. - /// - /// @result - /// A shared pointer to the breakpoint site. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointSiteSP - FindByID (lldb::break_id_t breakID) const; - - //------------------------------------------------------------------ - /// Returns the breakpoint site id to the breakpoint site at address \a addr. - /// - /// @param[in] addr - /// The address to match. - /// - /// @result - /// The ID of the breakpoint site, or LLDB_INVALID_BREAK_ID. - //------------------------------------------------------------------ - lldb::break_id_t - FindIDByAddress (lldb::addr_t addr); - - //------------------------------------------------------------------ - /// Returns whether the breakpoint site \a bp_site_id has \a bp_id - // as one of its owners. - /// - /// @param[in] bp_site_id - /// The breakpoint site id to query. - /// - /// @param[in] bp_id - /// The breakpoint id to look for in \a bp_site_id. - /// - /// @result - /// True if \a bp_site_id exists in the site list AND \a bp_id is one of the - /// owners of that site. - //------------------------------------------------------------------ - bool - BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id); - - void - ForEach (std::function <void(BreakpointSite *)> const &callback); - - //------------------------------------------------------------------ - /// Removes the breakpoint site given by \b breakID from this list. - /// - /// @param[in] breakID - /// The breakpoint site index to remove. - /// - /// @result - /// \b true if the breakpoint site \a breakID was in the list. - //------------------------------------------------------------------ - bool - Remove (lldb::break_id_t breakID); - - //------------------------------------------------------------------ - /// Removes the breakpoint site at address \a addr from this list. - /// - /// @param[in] addr - /// The address from which to remove a breakpoint site. - /// - /// @result - /// \b true if \a addr had a breakpoint site to remove from the list. - //------------------------------------------------------------------ - bool - RemoveByAddress (lldb::addr_t addr); - - bool - FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const; - - typedef void (*BreakpointSiteSPMapFunc) (lldb::BreakpointSiteSP &bp, void *baton); - - //------------------------------------------------------------------ - /// Enquires of the breakpoint site on in this list with ID \a breakID whether - /// we should stop for the breakpoint or not. - /// - /// @param[in] context - /// This contains the information about this stop. - /// - /// @param[in] breakID - /// This break ID that we hit. - /// - /// @return - /// \b true if we should stop, \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldStop (StoppointCallbackContext *context, lldb::break_id_t breakID); - - //------------------------------------------------------------------ - /// Returns the number of elements in the list. - /// - /// @result - /// The number of elements. - //------------------------------------------------------------------ - size_t - GetSize() const - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_bp_site_list.size(); - } - - bool - IsEmpty() const - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_bp_site_list.empty(); - } + //------------------------------------------------------------------ + /// Default constructor makes an empty list. + //------------------------------------------------------------------ + BreakpointSiteList(); + + //------------------------------------------------------------------ + /// Destructor, currently does nothing. + //------------------------------------------------------------------ + ~BreakpointSiteList(); + + //------------------------------------------------------------------ + /// Add a BreakpointSite to the list. + /// + /// @param[in] bp_site_sp + /// A shared pointer to a breakpoint site being added to the list. + /// + /// @return + /// The ID of the BreakpointSite in the list. + //------------------------------------------------------------------ + lldb::break_id_t Add(const lldb::BreakpointSiteSP &bp_site_sp); + + //------------------------------------------------------------------ + /// Standard Dump routine, doesn't do anything at present. + /// @param[in] s + /// Stream into which to dump the description. + //------------------------------------------------------------------ + void Dump(Stream *s) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint site at address + /// \a addr. + /// + /// @param[in] addr + /// The address to look for. + /// + /// @result + /// A shared pointer to the breakpoint site. May contain a NULL + /// pointer if no breakpoint site exists with a matching address. + //------------------------------------------------------------------ + lldb::BreakpointSiteSP FindByAddress(lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint site with id \a breakID. + /// + /// @param[in] breakID + /// The breakpoint site ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint site. May contain a NULL pointer if + /// the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointSiteSP FindByID(lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint site with id \a breakID - const + /// version. + /// + /// @param[in] breakID + /// The breakpoint site ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint site. May contain a NULL pointer if + /// the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointSiteSP FindByID(lldb::break_id_t breakID) const; + + //------------------------------------------------------------------ + /// Returns the breakpoint site id to the breakpoint site at address \a addr. + /// + /// @param[in] addr + /// The address to match. + /// + /// @result + /// The ID of the breakpoint site, or LLDB_INVALID_BREAK_ID. + //------------------------------------------------------------------ + lldb::break_id_t FindIDByAddress(lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns whether the breakpoint site \a bp_site_id has \a bp_id + // as one of its owners. + /// + /// @param[in] bp_site_id + /// The breakpoint site id to query. + /// + /// @param[in] bp_id + /// The breakpoint id to look for in \a bp_site_id. + /// + /// @result + /// True if \a bp_site_id exists in the site list AND \a bp_id is one of the + /// owners of that site. + //------------------------------------------------------------------ + bool BreakpointSiteContainsBreakpoint(lldb::break_id_t bp_site_id, + lldb::break_id_t bp_id); + + void ForEach(std::function<void(BreakpointSite *)> const &callback); + + //------------------------------------------------------------------ + /// Removes the breakpoint site given by \b breakID from this list. + /// + /// @param[in] breakID + /// The breakpoint site index to remove. + /// + /// @result + /// \b true if the breakpoint site \a breakID was in the list. + //------------------------------------------------------------------ + bool Remove(lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Removes the breakpoint site at address \a addr from this list. + /// + /// @param[in] addr + /// The address from which to remove a breakpoint site. + /// + /// @result + /// \b true if \a addr had a breakpoint site to remove from the list. + //------------------------------------------------------------------ + bool RemoveByAddress(lldb::addr_t addr); + + bool FindInRange(lldb::addr_t lower_bound, lldb::addr_t upper_bound, + BreakpointSiteList &bp_site_list) const; + + typedef void (*BreakpointSiteSPMapFunc)(lldb::BreakpointSiteSP &bp, + void *baton); + + //------------------------------------------------------------------ + /// Enquires of the breakpoint site on in this list with ID \a breakID whether + /// we should stop for the breakpoint or not. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] breakID + /// This break ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool ShouldStop(StoppointCallbackContext *context, lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns the number of elements in the list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t GetSize() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_bp_site_list.size(); + } + + bool IsEmpty() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_bp_site_list.empty(); + } protected: - typedef std::map<lldb::addr_t, lldb::BreakpointSiteSP> collection; + typedef std::map<lldb::addr_t, lldb::BreakpointSiteSP> collection; - collection::iterator - GetIDIterator(lldb::break_id_t breakID); + collection::iterator GetIDIterator(lldb::break_id_t breakID); - collection::const_iterator - GetIDConstIterator(lldb::break_id_t breakID) const; + collection::const_iterator GetIDConstIterator(lldb::break_id_t breakID) const; - mutable std::recursive_mutex m_mutex; - collection m_bp_site_list; // The breakpoint site list. + mutable std::recursive_mutex m_mutex; + collection m_bp_site_list; // The breakpoint site list. }; } // namespace lldb_private -#endif // liblldb_BreakpointSiteList_h_ +#endif // liblldb_BreakpointSiteList_h_ diff --git a/include/lldb/Breakpoint/Stoppoint.h b/include/lldb/Breakpoint/Stoppoint.h index c294830f15ec..5d131a556ad1 100644 --- a/include/lldb/Breakpoint/Stoppoint.h +++ b/include/lldb/Breakpoint/Stoppoint.h @@ -14,50 +14,43 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/UserID.h" +#include "lldb/lldb-private.h" namespace lldb_private { -class Stoppoint -{ +class Stoppoint { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - Stoppoint(); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Stoppoint(); - virtual - ~Stoppoint(); + virtual ~Stoppoint(); - //------------------------------------------------------------------ - // Methods - //------------------------------------------------------------------ - virtual void - Dump (Stream *) = 0; + //------------------------------------------------------------------ + // Methods + //------------------------------------------------------------------ + virtual void Dump(Stream *) = 0; - virtual bool - IsEnabled () = 0; + virtual bool IsEnabled() = 0; - virtual void - SetEnabled (bool enable) = 0; + virtual void SetEnabled(bool enable) = 0; - lldb::break_id_t - GetID () const; + lldb::break_id_t GetID() const; - void - SetID (lldb::break_id_t bid); + void SetID(lldb::break_id_t bid); protected: - lldb::break_id_t m_bid; + lldb::break_id_t m_bid; private: - //------------------------------------------------------------------ - // For Stoppoint only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (Stoppoint); + //------------------------------------------------------------------ + // For Stoppoint only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(Stoppoint); }; } // namespace lldb_private -#endif // liblldb_Stoppoint_h_ +#endif // liblldb_Stoppoint_h_ diff --git a/include/lldb/Breakpoint/StoppointCallbackContext.h b/include/lldb/Breakpoint/StoppointCallbackContext.h index 78327e291340..2680584845d7 100644 --- a/include/lldb/Breakpoint/StoppointCallbackContext.h +++ b/include/lldb/Breakpoint/StoppointCallbackContext.h @@ -10,49 +10,54 @@ #ifndef liblldb_StoppointCallbackContext_h_ #define liblldb_StoppointCallbackContext_h_ -#include "lldb/lldb-private.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class StoppointCallbackContext StoppointCallbackContext.h "lldb/Breakpoint/StoppointCallbackContext.h" -/// @brief Class holds the information that a breakpoint callback needs to evaluate this stop. +/// @class StoppointCallbackContext StoppointCallbackContext.h +/// "lldb/Breakpoint/StoppointCallbackContext.h" +/// @brief Class holds the information that a breakpoint callback needs to +/// evaluate this stop. //---------------------------------------------------------------------- //---------------------------------------------------------------------- /// General Outline: -/// When we hit a breakpoint we need to package up whatever information is needed -/// to evaluate breakpoint commands and conditions. This class is the container of +/// When we hit a breakpoint we need to package up whatever information is +/// needed +/// to evaluate breakpoint commands and conditions. This class is the container +/// of /// that information. //---------------------------------------------------------------------- -class StoppointCallbackContext -{ +class StoppointCallbackContext { public: - StoppointCallbackContext(); - - StoppointCallbackContext(Event *event, const ExecutionContext &exe_ctx, bool synchronously = false); - - //------------------------------------------------------------------ - /// Clear the object's state. - /// - /// Sets the event, process and thread to NULL, and the frame index to an - /// invalid value. - //------------------------------------------------------------------ - void - Clear (); - - //------------------------------------------------------------------ - // Member variables - //------------------------------------------------------------------ - Event *event; // This is the event, the callback can modify this to indicate - // the meaning of the breakpoint hit - ExecutionContextRef exe_ctx_ref; // This tells us where we have stopped, what thread. - bool is_synchronous; // Is the callback being executed synchronously with the breakpoint, - // or asynchronously as the event is retrieved? + StoppointCallbackContext(); + + StoppointCallbackContext(Event *event, const ExecutionContext &exe_ctx, + bool synchronously = false); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the event, process and thread to NULL, and the frame index to an + /// invalid value. + //------------------------------------------------------------------ + void Clear(); + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + Event *event; // This is the event, the callback can modify this to indicate + // the meaning of the breakpoint hit + ExecutionContextRef + exe_ctx_ref; // This tells us where we have stopped, what thread. + bool is_synchronous; // Is the callback being executed synchronously with the + // breakpoint, + // or asynchronously as the event is retrieved? }; } // namespace lldb_private -#endif // liblldb_StoppointCallbackContext_h_ +#endif // liblldb_StoppointCallbackContext_h_ diff --git a/include/lldb/Breakpoint/StoppointLocation.h b/include/lldb/Breakpoint/StoppointLocation.h index 32a1dbd4386e..ba03b4ea1f5b 100644 --- a/include/lldb/Breakpoint/StoppointLocation.h +++ b/include/lldb/Breakpoint/StoppointLocation.h @@ -14,137 +14,88 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/UserID.h" +#include "lldb/lldb-private.h" // #include "lldb/Breakpoint/BreakpointOptions.h" namespace lldb_private { -class StoppointLocation -{ +class StoppointLocation { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - StoppointLocation (lldb::break_id_t bid, - lldb::addr_t m_addr, - bool hardware); - - StoppointLocation (lldb::break_id_t bid, - lldb::addr_t m_addr, - uint32_t byte_size, - bool hardware); - - virtual - ~StoppointLocation (); - - //------------------------------------------------------------------ - // Operators - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - // Methods - //------------------------------------------------------------------ - virtual lldb::addr_t - GetLoadAddress() const - { - return m_addr; - } - - virtual void - SetLoadAddress (lldb::addr_t addr) - { - m_addr = addr; - } - - uint32_t - GetByteSize () const - { - return m_byte_size; - } - - uint32_t - GetHitCount () const - { - return m_hit_count; - } - - uint32_t - GetHardwareIndex () const - { - return m_hardware_index; - } - - - bool - HardwareRequired () const - { - return m_hardware; - } - - virtual bool - IsHardware () const - { - return m_hardware_index != LLDB_INVALID_INDEX32; - } - - - virtual bool - ShouldStop (StoppointCallbackContext *context) - { - return true; - } - - virtual void - Dump (Stream *stream) const - { - } - - void - SetHardwareIndex (uint32_t index) - { - m_hardware_index = index; - } - - - lldb::break_id_t - GetID () const - { - return m_loc_id; - } + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StoppointLocation(lldb::break_id_t bid, lldb::addr_t m_addr, bool hardware); + + StoppointLocation(lldb::break_id_t bid, lldb::addr_t m_addr, + uint32_t byte_size, bool hardware); + + virtual ~StoppointLocation(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + // Methods + //------------------------------------------------------------------ + virtual lldb::addr_t GetLoadAddress() const { return m_addr; } + + virtual void SetLoadAddress(lldb::addr_t addr) { m_addr = addr; } + + uint32_t GetByteSize() const { return m_byte_size; } + + uint32_t GetHitCount() const { return m_hit_count; } + + uint32_t GetHardwareIndex() const { return m_hardware_index; } + + bool HardwareRequired() const { return m_hardware; } + + virtual bool IsHardware() const { + return m_hardware_index != LLDB_INVALID_INDEX32; + } + + virtual bool ShouldStop(StoppointCallbackContext *context) { return true; } + + virtual void Dump(Stream *stream) const {} + + void SetHardwareIndex(uint32_t index) { m_hardware_index = index; } + + lldb::break_id_t GetID() const { return m_loc_id; } protected: - //------------------------------------------------------------------ - // Classes that inherit from StoppointLocation can see and modify these - //------------------------------------------------------------------ - lldb::break_id_t m_loc_id; // Stoppoint location ID - lldb::addr_t m_addr; // The load address of this stop point. The base Stoppoint doesn't - // store a full Address since that's not needed for the breakpoint sites. - bool m_hardware; // True if this point has been is required to use hardware (which may fail due to lack of resources) - uint32_t m_hardware_index; // The hardware resource index for this breakpoint/watchpoint - uint32_t m_byte_size; // The size in bytes of stop location. e.g. the length of the trap opcode for - // software breakpoints, or the optional length in bytes for - // hardware breakpoints, or the length of the watchpoint. - uint32_t m_hit_count; // Number of times this breakpoint/watchpoint has been hit - - // If you override this, be sure to call the base class to increment the internal counter. - void - IncrementHitCount () - { - ++m_hit_count; - } - - void - DecrementHitCount (); + //------------------------------------------------------------------ + // Classes that inherit from StoppointLocation can see and modify these + //------------------------------------------------------------------ + lldb::break_id_t m_loc_id; // Stoppoint location ID + lldb::addr_t + m_addr; // The load address of this stop point. The base Stoppoint doesn't + // store a full Address since that's not needed for the breakpoint sites. + bool m_hardware; // True if this point has been is required to use hardware + // (which may fail due to lack of resources) + uint32_t m_hardware_index; // The hardware resource index for this + // breakpoint/watchpoint + uint32_t m_byte_size; // The size in bytes of stop location. e.g. the length + // of the trap opcode for + // software breakpoints, or the optional length in bytes for + // hardware breakpoints, or the length of the watchpoint. + uint32_t + m_hit_count; // Number of times this breakpoint/watchpoint has been hit + + // If you override this, be sure to call the base class to increment the + // internal counter. + void IncrementHitCount() { ++m_hit_count; } + + void DecrementHitCount(); private: - //------------------------------------------------------------------ - // For StoppointLocation only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN(StoppointLocation); - StoppointLocation(); // Disallow default constructor + //------------------------------------------------------------------ + // For StoppointLocation only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(StoppointLocation); + StoppointLocation(); // Disallow default constructor }; } // namespace lldb_private -#endif // liblldb_StoppointLocation_h_ +#endif // liblldb_StoppointLocation_h_ diff --git a/include/lldb/Breakpoint/Watchpoint.h b/include/lldb/Breakpoint/Watchpoint.h index 34df24a92c06..97f2e282acc2 100644 --- a/include/lldb/Breakpoint/Watchpoint.h +++ b/include/lldb/Breakpoint/Watchpoint.h @@ -17,240 +17,218 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Breakpoint/StoppointLocation.h" +#include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/UserID.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" +#include "lldb/lldb-private.h" namespace lldb_private { -class Watchpoint : - public std::enable_shared_from_this<Watchpoint>, - public StoppointLocation -{ +class Watchpoint : public std::enable_shared_from_this<Watchpoint>, + public StoppointLocation { public: - class WatchpointEventData : - public EventData - { - public: - WatchpointEventData (lldb::WatchpointEventType sub_type, - const lldb::WatchpointSP &new_watchpoint_sp); - - ~WatchpointEventData() override; - - static const ConstString & - GetFlavorString (); - - const ConstString & - GetFlavor() const override; - - lldb::WatchpointEventType - GetWatchpointEventType () const; - - lldb::WatchpointSP & - GetWatchpoint (); - - void - Dump(Stream *s) const override; - - static lldb::WatchpointEventType - GetWatchpointEventTypeFromEvent (const lldb::EventSP &event_sp); - - static lldb::WatchpointSP - GetWatchpointFromEvent (const lldb::EventSP &event_sp); - - static const WatchpointEventData * - GetEventDataFromEvent (const Event *event_sp); - - private: - lldb::WatchpointEventType m_watchpoint_event; - lldb::WatchpointSP m_new_watchpoint_sp; - - DISALLOW_COPY_AND_ASSIGN (WatchpointEventData); - }; - - Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const CompilerType *type, bool hardware = true); - - ~Watchpoint() override; - - void - IncrementFalseAlarmsAndReviseHitCount(); - - bool - IsEnabled () const; - - void - SetEnabled (bool enabled, bool notify = true); - - bool - IsHardware() const override; - - bool - ShouldStop(StoppointCallbackContext *context) override; - - bool WatchpointRead () const; - bool WatchpointWrite () const; - uint32_t GetIgnoreCount () const; - void SetIgnoreCount (uint32_t n); - void SetWatchpointType (uint32_t type, bool notify = true); - void SetDeclInfo (const std::string &str); - std::string GetWatchSpec(); - void SetWatchSpec (const std::string &str); - - // Snapshot management interface. - bool IsWatchVariable() const; - void SetWatchVariable(bool val); - bool CaptureWatchedValue (const ExecutionContext &exe_ctx); - - void GetDescription (Stream *s, lldb::DescriptionLevel level); - void Dump (Stream *s) const override; - void DumpSnapshots(Stream *s, const char *prefix = nullptr) const; - void DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const; - Target &GetTarget() { return m_target; } - const Error &GetError() { return m_error; } - - //------------------------------------------------------------------ - /// Returns the WatchpointOptions structure set for this watchpoint. - /// - /// @return - /// A pointer to this watchpoint's WatchpointOptions. - //------------------------------------------------------------------ - WatchpointOptions * - GetOptions () { return &m_options; } - - //------------------------------------------------------------------ - /// Set the callback action invoked when the watchpoint is hit. - /// - /// @param[in] callback - /// The method that will get called when the watchpoint is hit. - /// @param[in] callback_baton - /// A void * pointer that will get passed back to the callback function. - /// @param[in] is_synchronous - /// If \b true the callback will be run on the private event thread - /// before the stop event gets reported. If false, the callback will get - /// handled on the public event thread after the stop has been posted. - /// - /// @return - /// \b true if the process should stop when you hit the watchpoint. - /// \b false if it should continue. - //------------------------------------------------------------------ - void - SetCallback (WatchpointHitCallback callback, - void *callback_baton, - bool is_synchronous = false); - - void - SetCallback (WatchpointHitCallback callback, - const lldb::BatonSP &callback_baton_sp, - bool is_synchronous = false); - - void ClearCallback(); - - //------------------------------------------------------------------ - /// Invoke the callback action when the watchpoint is hit. - /// - /// @param[in] context - /// Described the watchpoint event. - /// - /// @return - /// \b true if the target should stop at this watchpoint and \b false not. - //------------------------------------------------------------------ - bool - InvokeCallback (StoppointCallbackContext *context); - - //------------------------------------------------------------------ - // Condition - //------------------------------------------------------------------ - //------------------------------------------------------------------ - /// Set the watchpoint's condition. - /// - /// @param[in] condition - /// The condition expression to evaluate when the watchpoint is hit. - /// Pass in nullptr to clear the condition. - //------------------------------------------------------------------ - void SetCondition (const char *condition); - - //------------------------------------------------------------------ - /// Return a pointer to the text of the condition expression. - /// - /// @return - /// A pointer to the condition expression text, or nullptr if no - // condition has been set. - //------------------------------------------------------------------ - const char *GetConditionText () const; - - void - TurnOnEphemeralMode(); - - void - TurnOffEphemeralMode(); - - bool - IsDisabledDuringEphemeralMode(); - - const CompilerType & - GetCompilerType() - { - return m_type; - } + class WatchpointEventData : public EventData { + public: + WatchpointEventData(lldb::WatchpointEventType sub_type, + const lldb::WatchpointSP &new_watchpoint_sp); + + ~WatchpointEventData() override; + + static const ConstString &GetFlavorString(); + + const ConstString &GetFlavor() const override; + + lldb::WatchpointEventType GetWatchpointEventType() const; + + lldb::WatchpointSP &GetWatchpoint(); + + void Dump(Stream *s) const override; + + static lldb::WatchpointEventType + GetWatchpointEventTypeFromEvent(const lldb::EventSP &event_sp); + + static lldb::WatchpointSP + GetWatchpointFromEvent(const lldb::EventSP &event_sp); + + static const WatchpointEventData * + GetEventDataFromEvent(const Event *event_sp); + + private: + lldb::WatchpointEventType m_watchpoint_event; + lldb::WatchpointSP m_new_watchpoint_sp; + + DISALLOW_COPY_AND_ASSIGN(WatchpointEventData); + }; + + Watchpoint(Target &target, lldb::addr_t addr, uint32_t size, + const CompilerType *type, bool hardware = true); + + ~Watchpoint() override; + + void IncrementFalseAlarmsAndReviseHitCount(); + + bool IsEnabled() const; + + // This doesn't really enable/disable the watchpoint. + // It is currently just for use in the Process plugin's + // {Enable,Disable}Watchpoint, which should be used instead. + + void SetEnabled(bool enabled, bool notify = true); + + bool IsHardware() const override; + + bool ShouldStop(StoppointCallbackContext *context) override; + + bool WatchpointRead() const; + bool WatchpointWrite() const; + uint32_t GetIgnoreCount() const; + void SetIgnoreCount(uint32_t n); + void SetWatchpointType(uint32_t type, bool notify = true); + void SetDeclInfo(const std::string &str); + std::string GetWatchSpec(); + void SetWatchSpec(const std::string &str); + + // Snapshot management interface. + bool IsWatchVariable() const; + void SetWatchVariable(bool val); + bool CaptureWatchedValue(const ExecutionContext &exe_ctx); + + void GetDescription(Stream *s, lldb::DescriptionLevel level); + void Dump(Stream *s) const override; + void DumpSnapshots(Stream *s, const char *prefix = nullptr) const; + void DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const; + Target &GetTarget() { return m_target; } + const Error &GetError() { return m_error; } + + //------------------------------------------------------------------ + /// Returns the WatchpointOptions structure set for this watchpoint. + /// + /// @return + /// A pointer to this watchpoint's WatchpointOptions. + //------------------------------------------------------------------ + WatchpointOptions *GetOptions() { return &m_options; } + + //------------------------------------------------------------------ + /// Set the callback action invoked when the watchpoint is hit. + /// + /// @param[in] callback + /// The method that will get called when the watchpoint is hit. + /// @param[in] callback_baton + /// A void * pointer that will get passed back to the callback function. + /// @param[in] is_synchronous + /// If \b true the callback will be run on the private event thread + /// before the stop event gets reported. If false, the callback will get + /// handled on the public event thread after the stop has been posted. + /// + /// @return + /// \b true if the process should stop when you hit the watchpoint. + /// \b false if it should continue. + //------------------------------------------------------------------ + void SetCallback(WatchpointHitCallback callback, void *callback_baton, + bool is_synchronous = false); + + void SetCallback(WatchpointHitCallback callback, + const lldb::BatonSP &callback_baton_sp, + bool is_synchronous = false); + + void ClearCallback(); + + //------------------------------------------------------------------ + /// Invoke the callback action when the watchpoint is hit. + /// + /// @param[in] context + /// Described the watchpoint event. + /// + /// @return + /// \b true if the target should stop at this watchpoint and \b false not. + //------------------------------------------------------------------ + bool InvokeCallback(StoppointCallbackContext *context); + + //------------------------------------------------------------------ + // Condition + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Set the watchpoint's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the watchpoint is hit. + /// Pass in nullptr to clear the condition. + //------------------------------------------------------------------ + void SetCondition(const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or nullptr if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText() const; + + void TurnOnEphemeralMode(); + + void TurnOffEphemeralMode(); + + bool IsDisabledDuringEphemeralMode(); + + const CompilerType &GetCompilerType() { return m_type; } private: - friend class Target; - friend class WatchpointList; - - void - ResetHitCount () - { - m_hit_count = 0; - } - - void - ResetHistoricValues () - { - m_old_value_sp.reset(nullptr); - m_new_value_sp.reset(nullptr); - } - - Target &m_target; - bool m_enabled; // Is this watchpoint enabled - bool m_is_hardware; // Is this a hardware watchpoint - bool m_is_watch_variable; // True if set via 'watchpoint set variable'. - bool m_is_ephemeral; // True if the watchpoint is in the ephemeral mode, meaning that it is - // undergoing a pair of temporary disable/enable actions to avoid recursively - // triggering further watchpoint events. - uint32_t m_disabled_count; // Keep track of the count that the watchpoint is disabled while in ephemeral mode. - // At the end of the ephemeral mode when the watchpoint is to be enabled again, - // we check the count, if it is more than 1, it means the user-supplied actions - // actually want the watchpoint to be disabled! - uint32_t m_watch_read:1, // 1 if we stop when the watched data is read from - m_watch_write:1, // 1 if we stop when the watched data is written to - m_watch_was_read:1, // Set to 1 when watchpoint is hit for a read access - m_watch_was_written:1; // Set to 1 when watchpoint is hit for a write access - uint32_t m_ignore_count; // Number of times to ignore this watchpoint - uint32_t m_false_alarms; // Number of false alarms. - std::string m_decl_str; // Declaration information, if any. - std::string m_watch_spec_str; // Spec for the watchpoint. - lldb::ValueObjectSP m_old_value_sp; - lldb::ValueObjectSP m_new_value_sp; - CompilerType m_type; - Error m_error; // An error object describing errors associated with this watchpoint. - WatchpointOptions m_options; // Settable watchpoint options, which is a delegate to handle - // the callback machinery. - bool m_being_created; - - std::unique_ptr<UserExpression> m_condition_ap; // The condition to test. - - void SetID(lldb::watch_id_t id) { m_loc_id = id; } - - void - SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind); - - void - SendWatchpointChangedEvent (WatchpointEventData *data); - - DISALLOW_COPY_AND_ASSIGN (Watchpoint); + friend class Target; + friend class WatchpointList; + + void ResetHitCount() { m_hit_count = 0; } + + void ResetHistoricValues() { + m_old_value_sp.reset(nullptr); + m_new_value_sp.reset(nullptr); + } + + Target &m_target; + bool m_enabled; // Is this watchpoint enabled + bool m_is_hardware; // Is this a hardware watchpoint + bool m_is_watch_variable; // True if set via 'watchpoint set variable'. + bool m_is_ephemeral; // True if the watchpoint is in the ephemeral mode, + // meaning that it is + // undergoing a pair of temporary disable/enable actions to avoid recursively + // triggering further watchpoint events. + uint32_t m_disabled_count; // Keep track of the count that the watchpoint is + // disabled while in ephemeral mode. + // At the end of the ephemeral mode when the watchpoint is to be enabled + // again, + // we check the count, if it is more than 1, it means the user-supplied + // actions + // actually want the watchpoint to be disabled! + uint32_t m_watch_read : 1, // 1 if we stop when the watched data is read from + m_watch_write : 1, // 1 if we stop when the watched data is written to + m_watch_was_read : 1, // Set to 1 when watchpoint is hit for a read access + m_watch_was_written : 1; // Set to 1 when watchpoint is hit for a write + // access + uint32_t m_ignore_count; // Number of times to ignore this watchpoint + uint32_t m_false_alarms; // Number of false alarms. + std::string m_decl_str; // Declaration information, if any. + std::string m_watch_spec_str; // Spec for the watchpoint. + lldb::ValueObjectSP m_old_value_sp; + lldb::ValueObjectSP m_new_value_sp; + CompilerType m_type; + Error m_error; // An error object describing errors associated with this + // watchpoint. + WatchpointOptions + m_options; // Settable watchpoint options, which is a delegate to handle + // the callback machinery. + bool m_being_created; + + std::unique_ptr<UserExpression> m_condition_ap; // The condition to test. + + void SetID(lldb::watch_id_t id) { m_loc_id = id; } + + void SendWatchpointChangedEvent(lldb::WatchpointEventType eventKind); + + void SendWatchpointChangedEvent(WatchpointEventData *data); + + DISALLOW_COPY_AND_ASSIGN(Watchpoint); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/WatchpointList.h b/include/lldb/Breakpoint/WatchpointList.h index 7369623d1ce2..9abac9167b0b 100644 --- a/include/lldb/Breakpoint/WatchpointList.h +++ b/include/lldb/Breakpoint/WatchpointList.h @@ -18,8 +18,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" +#include "lldb/lldb-private.h" namespace lldb_private { @@ -30,248 +30,224 @@ namespace lldb_private { // well. //---------------------------------------------------------------------- -class WatchpointList -{ -// Only Target can make the watchpoint list, or add elements to it. -// This is not just some random collection of watchpoints. Rather, the act of -// adding the watchpoint to this list sets its ID. -friend class Watchpoint; -friend class Target; +class WatchpointList { + // Only Target can make the watchpoint list, or add elements to it. + // This is not just some random collection of watchpoints. Rather, the act of + // adding the watchpoint to this list sets its ID. + friend class Watchpoint; + friend class Target; public: - //------------------------------------------------------------------ - /// Default constructor makes an empty list. - //------------------------------------------------------------------ - WatchpointList(); - - //------------------------------------------------------------------ - /// Destructor, currently does nothing. - //------------------------------------------------------------------ - ~WatchpointList(); - - //------------------------------------------------------------------ - /// Add a Watchpoint to the list. - /// - /// @param[in] wp_sp - /// A shared pointer to a watchpoint being added to the list. - /// - /// @return - /// The ID of the Watchpoint in the list. - //------------------------------------------------------------------ - lldb::watch_id_t - Add (const lldb::WatchpointSP& wp_sp, bool notify); - - //------------------------------------------------------------------ - /// Standard "Dump" method. - //------------------------------------------------------------------ - void - Dump (Stream *s) const; - - //------------------------------------------------------------------ - /// Dump with lldb::DescriptionLevel. - //------------------------------------------------------------------ - void - DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the watchpoint at address - /// \a addr - - /// const version. - /// - /// @param[in] addr - /// The address to look for. - /// - /// @result - /// A shared pointer to the watchpoint. May contain a NULL - /// pointer if the watchpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::WatchpointSP - FindByAddress (lldb::addr_t addr) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the watchpoint with watchpoint spec - /// \a spec - - /// const version. - /// - /// @param[in] spec - /// The watchpoint spec to look for. - /// - /// @result - /// A shared pointer to the watchpoint. May contain a NULL - /// pointer if the watchpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::WatchpointSP - FindBySpec (std::string spec) const; - - //------------------------------------------------------------------ - /// Returns a shared pointer to the watchpoint with id - /// \a watchID, const - /// version. - /// - /// @param[in] watchID - /// The watchpoint location ID to seek for. - /// - /// @result - /// A shared pointer to the watchpoint. May contain a NULL - /// pointer if the watchpoint doesn't exist. - //------------------------------------------------------------------ - lldb::WatchpointSP - FindByID (lldb::watch_id_t watchID) const; - - //------------------------------------------------------------------ - /// Returns the watchpoint id to the watchpoint - /// at address \a addr. - /// - /// @param[in] addr - /// The address to match. - /// - /// @result - /// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID. - //------------------------------------------------------------------ - lldb::watch_id_t - FindIDByAddress (lldb::addr_t addr); - - //------------------------------------------------------------------ - /// Returns the watchpoint id to the watchpoint - /// with watchpoint spec \a spec. - /// - /// @param[in] spec - /// The watchpoint spec to match. - /// - /// @result - /// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID. - //------------------------------------------------------------------ - lldb::watch_id_t - FindIDBySpec (std::string spec); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the watchpoint with index \a i. - /// - /// @param[in] i - /// The watchpoint index to seek for. - /// - /// @result - /// A shared pointer to the watchpoint. May contain a NULL pointer if - /// the watchpoint doesn't exist. - //------------------------------------------------------------------ - lldb::WatchpointSP - GetByIndex (uint32_t i); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the watchpoint with index \a i, const - /// version. - /// - /// @param[in] i - /// The watchpoint index to seek for. - /// - /// @result - /// A shared pointer to the watchpoint. May contain a NULL pointer if - /// the watchpoint location doesn't exist. - //------------------------------------------------------------------ - const lldb::WatchpointSP - GetByIndex (uint32_t i) const; - - //------------------------------------------------------------------ - /// Removes the watchpoint given by \b watchID from this list. - /// - /// @param[in] watchID - /// The watchpoint ID to remove. - /// - /// @result - /// \b true if the watchpoint \a watchID was in the list. - //------------------------------------------------------------------ - bool - Remove (lldb::watch_id_t watchID, bool notify); - - //------------------------------------------------------------------ - /// Returns the number hit count of all watchpoints in this list. - /// - /// @result - /// Hit count of all watchpoints in this list. - //------------------------------------------------------------------ - uint32_t - GetHitCount () const; - - //------------------------------------------------------------------ - /// Enquires of the watchpoint in this list with ID \a watchID whether we - /// should stop. - /// - /// @param[in] context - /// This contains the information about this stop. - /// - /// @param[in] watchID - /// This watch ID that we hit. - /// - /// @return - /// \b true if we should stop, \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldStop (StoppointCallbackContext *context, - lldb::watch_id_t watchID); - - //------------------------------------------------------------------ - /// Returns the number of elements in this watchpoint list. - /// - /// @result - /// The number of elements. - //------------------------------------------------------------------ - size_t - GetSize() const - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_watchpoints.size(); - } - - //------------------------------------------------------------------ - /// Print a description of the watchpoints in this list to the stream \a s. - /// - /// @param[in] s - /// The stream to which to print the description. - /// - /// @param[in] level - /// The description level that indicates the detail level to - /// provide. - /// - /// @see lldb::DescriptionLevel - //------------------------------------------------------------------ - void - GetDescription (Stream *s, - lldb::DescriptionLevel level); - - void - SetEnabledAll (bool enabled); - - void - RemoveAll (bool notify); - - //------------------------------------------------------------------ - /// Sets the passed in Locker to hold the Watchpoint List mutex. - /// - /// @param[in] locker - /// The locker object that is set. - //------------------------------------------------------------------ - void - GetListMutex(std::unique_lock<std::recursive_mutex> &lock); + //------------------------------------------------------------------ + /// Default constructor makes an empty list. + //------------------------------------------------------------------ + WatchpointList(); + + //------------------------------------------------------------------ + /// Destructor, currently does nothing. + //------------------------------------------------------------------ + ~WatchpointList(); + + //------------------------------------------------------------------ + /// Add a Watchpoint to the list. + /// + /// @param[in] wp_sp + /// A shared pointer to a watchpoint being added to the list. + /// + /// @return + /// The ID of the Watchpoint in the list. + //------------------------------------------------------------------ + lldb::watch_id_t Add(const lldb::WatchpointSP &wp_sp, bool notify); + + //------------------------------------------------------------------ + /// Standard "Dump" method. + //------------------------------------------------------------------ + void Dump(Stream *s) const; + + //------------------------------------------------------------------ + /// Dump with lldb::DescriptionLevel. + //------------------------------------------------------------------ + void DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint at address + /// \a addr - + /// const version. + /// + /// @param[in] addr + /// The address to look for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL + /// pointer if the watchpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::WatchpointSP FindByAddress(lldb::addr_t addr) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with watchpoint spec + /// \a spec - + /// const version. + /// + /// @param[in] spec + /// The watchpoint spec to look for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL + /// pointer if the watchpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::WatchpointSP FindBySpec(std::string spec) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with id + /// \a watchID, const + /// version. + /// + /// @param[in] watchID + /// The watchpoint location ID to seek for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL + /// pointer if the watchpoint doesn't exist. + //------------------------------------------------------------------ + lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const; + + //------------------------------------------------------------------ + /// Returns the watchpoint id to the watchpoint + /// at address \a addr. + /// + /// @param[in] addr + /// The address to match. + /// + /// @result + /// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID. + //------------------------------------------------------------------ + lldb::watch_id_t FindIDByAddress(lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns the watchpoint id to the watchpoint + /// with watchpoint spec \a spec. + /// + /// @param[in] spec + /// The watchpoint spec to match. + /// + /// @result + /// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID. + //------------------------------------------------------------------ + lldb::watch_id_t FindIDBySpec(std::string spec); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with index \a i. + /// + /// @param[in] i + /// The watchpoint index to seek for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL pointer if + /// the watchpoint doesn't exist. + //------------------------------------------------------------------ + lldb::WatchpointSP GetByIndex(uint32_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with index \a i, const + /// version. + /// + /// @param[in] i + /// The watchpoint index to seek for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL pointer if + /// the watchpoint location doesn't exist. + //------------------------------------------------------------------ + const lldb::WatchpointSP GetByIndex(uint32_t i) const; + + //------------------------------------------------------------------ + /// Removes the watchpoint given by \b watchID from this list. + /// + /// @param[in] watchID + /// The watchpoint ID to remove. + /// + /// @result + /// \b true if the watchpoint \a watchID was in the list. + //------------------------------------------------------------------ + bool Remove(lldb::watch_id_t watchID, bool notify); + + //------------------------------------------------------------------ + /// Returns the number hit count of all watchpoints in this list. + /// + /// @result + /// Hit count of all watchpoints in this list. + //------------------------------------------------------------------ + uint32_t GetHitCount() const; + + //------------------------------------------------------------------ + /// Enquires of the watchpoint in this list with ID \a watchID whether we + /// should stop. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] watchID + /// This watch ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool ShouldStop(StoppointCallbackContext *context, lldb::watch_id_t watchID); + + //------------------------------------------------------------------ + /// Returns the number of elements in this watchpoint list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t GetSize() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_watchpoints.size(); + } + + //------------------------------------------------------------------ + /// Print a description of the watchpoints in this list to the stream \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription(Stream *s, lldb::DescriptionLevel level); + + void SetEnabledAll(bool enabled); + + void RemoveAll(bool notify); + + //------------------------------------------------------------------ + /// Sets the passed in Locker to hold the Watchpoint List mutex. + /// + /// @param[in] locker + /// The locker object that is set. + //------------------------------------------------------------------ + void GetListMutex(std::unique_lock<std::recursive_mutex> &lock); protected: - typedef std::list<lldb::WatchpointSP> wp_collection; - typedef std::vector<lldb::watch_id_t> id_vector; + typedef std::list<lldb::WatchpointSP> wp_collection; + typedef std::vector<lldb::watch_id_t> id_vector; - id_vector - GetWatchpointIDs() const; + id_vector GetWatchpointIDs() const; - wp_collection::iterator - GetIDIterator(lldb::watch_id_t watchID); + wp_collection::iterator GetIDIterator(lldb::watch_id_t watchID); - wp_collection::const_iterator - GetIDConstIterator(lldb::watch_id_t watchID) const; + wp_collection::const_iterator + GetIDConstIterator(lldb::watch_id_t watchID) const; - wp_collection m_watchpoints; - mutable std::recursive_mutex m_mutex; + wp_collection m_watchpoints; + mutable std::recursive_mutex m_mutex; - lldb::watch_id_t m_next_wp_id; + lldb::watch_id_t m_next_wp_id; }; } // namespace lldb_private -#endif // liblldb_WatchpointList_h_ +#endif // liblldb_WatchpointList_h_ diff --git a/include/lldb/Breakpoint/WatchpointOptions.h b/include/lldb/Breakpoint/WatchpointOptions.h index eb08bb32e6ce..bfb814ecbd54 100644 --- a/include/lldb/Breakpoint/WatchpointOptions.h +++ b/include/lldb/Breakpoint/WatchpointOptions.h @@ -17,234 +17,228 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Baton.h" #include "lldb/Core/StringList.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class WatchpointOptions WatchpointOptions.h "lldb/Breakpoint/WatchpointOptions.h" +/// @class WatchpointOptions WatchpointOptions.h +/// "lldb/Breakpoint/WatchpointOptions.h" /// @brief Class that manages the options on a watchpoint. //---------------------------------------------------------------------- -class WatchpointOptions -{ +class WatchpointOptions { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - //------------------------------------------------------------------ - /// Default constructor. The watchpoint is enabled, and has no condition, - /// callback, ignore count, etc... - //------------------------------------------------------------------ - WatchpointOptions(); - WatchpointOptions(const WatchpointOptions& rhs); - - static WatchpointOptions * - CopyOptionsNoCallback (WatchpointOptions &rhs); - //------------------------------------------------------------------ - /// This constructor allows you to specify all the watchpoint options. - /// - /// @param[in] callback - /// This is the plugin for some code that gets run, returns \b true if we are to stop. - /// - /// @param[in] baton - /// Client data that will get passed to the callback. - /// - /// @param[in] thread_id - /// Only stop if \a thread_id hits the watchpoint. - //------------------------------------------------------------------ - WatchpointOptions(WatchpointHitCallback callback, - void *baton, - lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID); - - virtual ~WatchpointOptions(); - - //------------------------------------------------------------------ - // Operators - //------------------------------------------------------------------ - const WatchpointOptions& - operator=(const WatchpointOptions& rhs); - - //------------------------------------------------------------------ - // Callbacks - // - // Watchpoint callbacks come in two forms, synchronous and asynchronous. Synchronous callbacks will get - // run before any of the thread plans are consulted, and if they return false the target will continue - // "under the radar" of the thread plans. There are a couple of restrictions to synchronous callbacks: - // 1) They should NOT resume the target themselves. Just return false if you want the target to restart. - // 2) Watchpoints with synchronous callbacks can't have conditions (or rather, they can have them, but they - // won't do anything. Ditto with ignore counts, etc... You are supposed to control that all through the - // callback. - // Asynchronous callbacks get run as part of the "ShouldStop" logic in the thread plan. The logic there is: - // a) If the watchpoint is thread specific and not for this thread, continue w/o running the callback. - // 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. - // The asynchronous callback can run the target itself, but at present that should be the last action the - // callback does. We will relax this condition at some point, but it will take a bit of plumbing to get - // that to work. - // - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Adds a callback to the watchpoint option set. - /// - /// @param[in] callback - /// The function to be called when the watchpoint gets hit. - /// - /// @param[in] baton_sp - /// A baton which will get passed back to the callback when it is invoked. - /// - /// @param[in] synchronous - /// Whether this is a synchronous or asynchronous callback. See discussion above. - //------------------------------------------------------------------ - void SetCallback (WatchpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false); - - //------------------------------------------------------------------ - /// Remove the callback from this option set. - //------------------------------------------------------------------ - void ClearCallback (); - - // The rest of these functions are meant to be used only within the watchpoint handling mechanism. - - //------------------------------------------------------------------ - /// Use this function to invoke the callback for a specific stop. - /// - /// @param[in] context - /// The context in which the callback is to be invoked. This includes the stop event, the - /// execution context of the stop (since you might hit the same watchpoint on multiple threads) and - /// whether we are currently executing synchronous or asynchronous callbacks. - /// - /// @param[in] watch_id - /// The watchpoint ID that owns this option set. - /// - /// @return - /// The callback return value. - //------------------------------------------------------------------ - bool InvokeCallback (StoppointCallbackContext *context, lldb::user_id_t watch_id); - - //------------------------------------------------------------------ - /// Used in InvokeCallback to tell whether it is the right time to run this kind of callback. - /// - /// @return - /// The synchronicity of our callback. - //------------------------------------------------------------------ - bool IsCallbackSynchronous () { - return m_callback_is_synchronous; - } - - //------------------------------------------------------------------ - /// Fetch the baton from the callback. - /// - /// @return - /// The baton. - //------------------------------------------------------------------ - Baton *GetBaton (); - - //------------------------------------------------------------------ - /// Fetch a const version of the baton from the callback. - /// - /// @return - /// The baton. - //------------------------------------------------------------------ - const Baton *GetBaton () const; - - //------------------------------------------------------------------ - /// Return the current thread spec for this option. This will return nullptr if the no thread - /// specifications have been set for this Option yet. - /// @return - /// The thread specification pointer for this option, or nullptr if none has - /// been set yet. - //------------------------------------------------------------------ - const ThreadSpec * - GetThreadSpecNoCreate () const; - - //------------------------------------------------------------------ - /// Returns a pointer to the ThreadSpec for this option, creating it. - /// if it hasn't been created already. This API is used for setting the - /// ThreadSpec items for this option. - //------------------------------------------------------------------ - ThreadSpec * - GetThreadSpec (); - - void - SetThreadID(lldb::tid_t thread_id); - - void - GetDescription (Stream *s, lldb::DescriptionLevel level) const; - - //------------------------------------------------------------------ - /// Get description for callback only. - //------------------------------------------------------------------ - void - GetCallbackDescription (Stream *s, lldb::DescriptionLevel level) const; - - //------------------------------------------------------------------ - /// Returns true if the watchpoint option has a callback set. - //------------------------------------------------------------------ - bool - HasCallback(); - - //------------------------------------------------------------------ - /// This is the default empty callback. - /// @return - /// The thread id for which the watchpoint hit will stop, - /// LLDB_INVALID_THREAD_ID for all threads. - //------------------------------------------------------------------ - static bool - NullCallback (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t watch_id); - - struct CommandData - { - CommandData () : - user_source(), - script_source(), - stop_on_error(true) - { - } - - ~CommandData() = default; - - StringList user_source; - std::string script_source; - bool stop_on_error; - }; - - class CommandBaton : public Baton - { - public: - CommandBaton (CommandData *data) : - Baton (data) - { - } - - ~CommandBaton() override - { - delete ((CommandData *)m_data); - m_data = nullptr; - } - - void - GetDescription(Stream *s, lldb::DescriptionLevel level) const override; - }; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Default constructor. The watchpoint is enabled, and has no condition, + /// callback, ignore count, etc... + //------------------------------------------------------------------ + WatchpointOptions(); + WatchpointOptions(const WatchpointOptions &rhs); + + static WatchpointOptions *CopyOptionsNoCallback(WatchpointOptions &rhs); + //------------------------------------------------------------------ + /// This constructor allows you to specify all the watchpoint options. + /// + /// @param[in] callback + /// This is the plugin for some code that gets run, returns \b true if we + /// are to stop. + /// + /// @param[in] baton + /// Client data that will get passed to the callback. + /// + /// @param[in] thread_id + /// Only stop if \a thread_id hits the watchpoint. + //------------------------------------------------------------------ + WatchpointOptions(WatchpointHitCallback callback, void *baton, + lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID); + + virtual ~WatchpointOptions(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const WatchpointOptions &operator=(const WatchpointOptions &rhs); + + //------------------------------------------------------------------ + // Callbacks + // + // Watchpoint callbacks come in two forms, synchronous and asynchronous. + // Synchronous callbacks will get + // run before any of the thread plans are consulted, and if they return false + // the target will continue + // "under the radar" of the thread plans. There are a couple of restrictions + // to synchronous callbacks: + // 1) They should NOT resume the target themselves. Just return false if you + // want the target to restart. + // 2) Watchpoints with synchronous callbacks can't have conditions (or rather, + // they can have them, but they + // won't do anything. Ditto with ignore counts, etc... You are supposed + // to control that all through the + // callback. + // Asynchronous callbacks get run as part of the "ShouldStop" logic in the + // thread plan. The logic there is: + // a) If the watchpoint is thread specific and not for this thread, continue + // w/o running the callback. + // 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. + // The asynchronous callback can run the target itself, but at present that + // should be the last action the + // callback does. We will relax this condition at some point, but it will + // take a bit of plumbing to get + // that to work. + // + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Adds a callback to the watchpoint option set. + /// + /// @param[in] callback + /// The function to be called when the watchpoint gets hit. + /// + /// @param[in] baton_sp + /// A baton which will get passed back to the callback when it is invoked. + /// + /// @param[in] synchronous + /// Whether this is a synchronous or asynchronous callback. See discussion + /// above. + //------------------------------------------------------------------ + void SetCallback(WatchpointHitCallback callback, + const lldb::BatonSP &baton_sp, bool synchronous = false); + + //------------------------------------------------------------------ + /// Remove the callback from this option set. + //------------------------------------------------------------------ + void ClearCallback(); + + // The rest of these functions are meant to be used only within the watchpoint + // handling mechanism. + + //------------------------------------------------------------------ + /// Use this function to invoke the callback for a specific stop. + /// + /// @param[in] context + /// The context in which the callback is to be invoked. This includes the + /// stop event, the + /// execution context of the stop (since you might hit the same watchpoint + /// on multiple threads) and + /// whether we are currently executing synchronous or asynchronous + /// callbacks. + /// + /// @param[in] watch_id + /// The watchpoint ID that owns this option set. + /// + /// @return + /// The callback return value. + //------------------------------------------------------------------ + bool InvokeCallback(StoppointCallbackContext *context, + lldb::user_id_t watch_id); + + //------------------------------------------------------------------ + /// Used in InvokeCallback to tell whether it is the right time to run this + /// kind of callback. + /// + /// @return + /// The synchronicity of our callback. + //------------------------------------------------------------------ + bool IsCallbackSynchronous() { return m_callback_is_synchronous; } + + //------------------------------------------------------------------ + /// Fetch the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + Baton *GetBaton(); + + //------------------------------------------------------------------ + /// Fetch a const version of the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + const Baton *GetBaton() const; + + //------------------------------------------------------------------ + /// Return the current thread spec for this option. This will return nullptr + /// if the no thread + /// specifications have been set for this Option yet. + /// @return + /// The thread specification pointer for this option, or nullptr if none + /// has + /// been set yet. + //------------------------------------------------------------------ + const ThreadSpec *GetThreadSpecNoCreate() const; + + //------------------------------------------------------------------ + /// Returns a pointer to the ThreadSpec for this option, creating it. + /// if it hasn't been created already. This API is used for setting the + /// ThreadSpec items for this option. + //------------------------------------------------------------------ + ThreadSpec *GetThreadSpec(); + + void SetThreadID(lldb::tid_t thread_id); + + void GetDescription(Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Get description for callback only. + //------------------------------------------------------------------ + void GetCallbackDescription(Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Returns true if the watchpoint option has a callback set. + //------------------------------------------------------------------ + bool HasCallback(); + + //------------------------------------------------------------------ + /// This is the default empty callback. + /// @return + /// The thread id for which the watchpoint hit will stop, + /// LLDB_INVALID_THREAD_ID for all threads. + //------------------------------------------------------------------ + static bool NullCallback(void *baton, StoppointCallbackContext *context, + lldb::user_id_t watch_id); + + struct CommandData { + CommandData() : user_source(), script_source(), stop_on_error(true) {} + + ~CommandData() = default; + + StringList user_source; + std::string script_source; + bool stop_on_error; + }; + + class CommandBaton : public TypedBaton<CommandData> { + public: + CommandBaton(std::unique_ptr<CommandData> Data) + : TypedBaton(std::move(Data)) {} + + void GetDescription(Stream *s, lldb::DescriptionLevel level) const override; + }; protected: - //------------------------------------------------------------------ - // Classes that inherit from WatchpointOptions can see and modify these - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Classes that inherit from WatchpointOptions can see and modify these + //------------------------------------------------------------------ private: - //------------------------------------------------------------------ - // For WatchpointOptions only - //------------------------------------------------------------------ - WatchpointHitCallback m_callback; // This is the callback function pointer - lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback - bool m_callback_is_synchronous; - std::unique_ptr<ThreadSpec> m_thread_spec_ap; // Thread for which this watchpoint will take + //------------------------------------------------------------------ + // For WatchpointOptions only + //------------------------------------------------------------------ + WatchpointHitCallback m_callback; // This is the callback function pointer + lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback + bool m_callback_is_synchronous; + std::unique_ptr<ThreadSpec> + m_thread_spec_ap; // Thread for which this watchpoint will take }; } // namespace lldb_private |