diff options
Diffstat (limited to 'include/lldb/Breakpoint/Breakpoint.h')
-rw-r--r-- | include/lldb/Breakpoint/Breakpoint.h | 1392 |
1 files changed, 677 insertions, 715 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 |