| //===-- BreakpointResolver.h ------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLDB_BREAKPOINT_BREAKPOINTRESOLVER_H |
| #define LLDB_BREAKPOINT_BREAKPOINTRESOLVER_H |
| |
| #include "lldb/Breakpoint/Breakpoint.h" |
| #include "lldb/Core/Address.h" |
| #include "lldb/Core/SearchFilter.h" |
| #include "lldb/Utility/ConstString.h" |
| #include "lldb/Utility/FileSpec.h" |
| #include "lldb/Utility/RegularExpression.h" |
| #include "lldb/lldb-private.h" |
| |
| namespace lldb_private { |
| |
| /// \class BreakpointResolver BreakpointResolver.h |
| /// "lldb/Breakpoint/BreakpointResolver.h" This class works with SearchFilter |
| /// to resolve logical breakpoints to their of concrete breakpoint locations. |
| |
| /// 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. |
| |
| 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. |
| BreakpointResolver(const lldb::BreakpointSP &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(const lldb::BreakpointSP &bkpt); |
| |
| /// This gets the breakpoint for this resolver. |
| lldb::BreakpointSP GetBreakpoint() const { |
| auto breakpoint_sp = m_breakpoint.expired() ? lldb::BreakpointSP() : |
| m_breakpoint.lock(); |
| assert(breakpoint_sp); |
| return breakpoint_sp; |
| } |
| |
| /// 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); |
| |
| 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, |
| Status &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, |
| PythonResolver, |
| 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(llvm::StringRef name); |
| |
| virtual lldb::BreakpointResolverSP |
| CopyForBreakpoint(lldb::BreakpointSP &breakpoint) = 0; |
| |
| protected: |
| // 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, |
| Column, |
| ModuleName, |
| NameMaskArray, |
| Offset, |
| PythonClassName, |
| RegexString, |
| ScriptArgs, |
| SectionName, |
| SearchDepth, |
| SkipPrologue, |
| SymbolNameArray, |
| LastOptionName |
| }; |
| static const char |
| *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)]; |
| |
| virtual void NotifyBreakpointSet() {}; |
| |
| public: |
| static const char *GetKey(OptionNames enum_value) { |
| return g_option_names[static_cast<uint32_t>(enum_value)]; |
| } |
| |
| protected: |
| /// 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. |
| /// When \p column is nonzero the \p line and \p column args are used to |
| /// filter the results to find the first breakpoint >= (line, column). |
| void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list, |
| bool skip_prologue, llvm::StringRef log_ident, |
| uint32_t line = 0, |
| llvm::Optional<uint16_t> column = llvm::None); |
| void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool, |
| const char *) = delete; |
| |
| lldb::BreakpointLocationSP AddLocation(Address loc_addr, |
| bool *new_location = nullptr); |
| |
| private: |
| /// Helper for \p SetSCMatchesByLine. |
| void AddLocation(SearchFilter &filter, const SymbolContext &sc, |
| bool skip_prologue, llvm::StringRef log_ident); |
| |
| lldb::BreakpointWP 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. |
| |
| // Subclass identifier (for llvm isa/dyn_cast) |
| const unsigned char SubclassID; |
| BreakpointResolver(const BreakpointResolver &) = delete; |
| const BreakpointResolver &operator=(const BreakpointResolver &) = delete; |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // LLDB_BREAKPOINT_BREAKPOINTRESOLVER_H |