1 //===-- BreakpointResolver.h ------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef liblldb_BreakpointResolver_h_
10 #define liblldb_BreakpointResolver_h_
11 
12 #include "lldb/Breakpoint/Breakpoint.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Core/SearchFilter.h"
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/RegularExpression.h"
18 #include "lldb/lldb-private.h"
19 
20 namespace lldb_private {
21 
22 /// \class BreakpointResolver BreakpointResolver.h
23 /// "lldb/Breakpoint/BreakpointResolver.h" This class works with SearchFilter
24 /// to resolve logical breakpoints to their of concrete breakpoint locations.
25 
26 /// General Outline:
27 /// The BreakpointResolver is a Searcher.  In that protocol, the SearchFilter
28 /// asks the question "At what depth of the symbol context descent do you want
29 /// your callback to get called?" of the filter.  The resolver answers this
30 /// question (in the GetDepth method) and provides the resolution callback.
31 /// Each Breakpoint has a BreakpointResolver, and it calls either
32 /// ResolveBreakpoint or ResolveBreakpointInModules to tell it to look for new
33 /// breakpoint locations.
34 
35 class BreakpointResolver : public Searcher {
36   friend class Breakpoint;
37 
38 public:
39   /// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint
40   /// to make sense.  It can be constructed without a breakpoint, but you have
41   /// to call SetBreakpoint before ResolveBreakpoint.
42   ///
43   /// \param[in] bkpt
44   ///   The breakpoint that owns this resolver.
45   /// \param[in] resolverType
46   ///   The concrete breakpoint resolver type for this breakpoint.
47   BreakpointResolver(Breakpoint *bkpt, unsigned char resolverType,
48                      lldb::addr_t offset = 0);
49 
50   /// The Destructor is virtual, all significant breakpoint resolvers derive
51   /// from this class.
52   ~BreakpointResolver() override;
53 
54   /// This sets the breakpoint for this resolver.
55   ///
56   /// \param[in] bkpt
57   ///   The breakpoint that owns this resolver.
58   void SetBreakpoint(Breakpoint *bkpt);
59 
60   /// This updates the offset for this breakpoint.  All the locations
61   /// currently set for this breakpoint will have their offset adjusted when
62   /// this is called.
63   ///
64   /// \param[in] offset
65   ///   The offset to add to all locations.
66   void SetOffset(lldb::addr_t offset);
67 
68   /// This updates the offset for this breakpoint.  All the locations
69   /// currently set for this breakpoint will have their offset adjusted when
70   /// this is called.
71   ///
72   /// \param[in] offset
73   ///   The offset to add to all locations.
74   lldb::addr_t GetOffset() const { return m_offset; }
75 
76   /// In response to this method the resolver scans all the modules in the
77   /// breakpoint's target, and adds any new locations it finds.
78   ///
79   /// \param[in] filter
80   ///   The filter that will manage the search for this resolver.
81   virtual void ResolveBreakpoint(SearchFilter &filter);
82 
83   /// In response to this method the resolver scans the modules in the module
84   /// list \a modules, and adds any new locations it finds.
85   ///
86   /// \param[in] filter
87   ///   The filter that will manage the search for this resolver.
88   virtual void ResolveBreakpointInModules(SearchFilter &filter,
89                                           ModuleList &modules);
90 
91   /// Prints a canonical description for the breakpoint to the stream \a s.
92   ///
93   /// \param[in] s
94   ///   Stream to which the output is copied.
95   void GetDescription(Stream *s) override = 0;
96 
97   /// Standard "Dump" method.  At present it does nothing.
98   virtual void Dump(Stream *s) const = 0;
99 
100   /// This section handles serializing and deserializing from StructuredData
101   /// objects.
102 
103   static lldb::BreakpointResolverSP
104   CreateFromStructuredData(const StructuredData::Dictionary &resolver_dict,
105                            Status &error);
106 
107   virtual StructuredData::ObjectSP SerializeToStructuredData() {
108     return StructuredData::ObjectSP();
109   }
110 
111   static const char *GetSerializationKey() { return "BKPTResolver"; }
112 
113   static const char *GetSerializationSubclassKey() { return "Type"; }
114 
115   static const char *GetSerializationSubclassOptionsKey() { return "Options"; }
116 
117   StructuredData::DictionarySP
118   WrapOptionsDict(StructuredData::DictionarySP options_dict_sp);
119 
120   /// An enumeration for keeping track of the concrete subclass that is
121   /// actually instantiated. Values of this enumeration are kept in the
122   /// BreakpointResolver's SubclassID field. They are used for concrete type
123   /// identification.
124   enum ResolverTy {
125     FileLineResolver = 0, // This is an instance of BreakpointResolverFileLine
126     AddressResolver,      // This is an instance of BreakpointResolverAddress
127     NameResolver,         // This is an instance of BreakpointResolverName
128     FileRegexResolver,
129     PythonResolver,
130     ExceptionResolver,
131     LastKnownResolverType = ExceptionResolver,
132     UnknownResolver
133   };
134 
135   // Translate the Ty to name for serialization, the "+2" is one for size vrs.
136   // index, and one for UnknownResolver.
137   static const char *g_ty_to_name[LastKnownResolverType + 2];
138 
139   /// getResolverID - Return an ID for the concrete type of this object.  This
140   /// is used to implement the LLVM classof checks.  This should not be used
141   /// for any other purpose, as the values may change as LLDB evolves.
142   unsigned getResolverID() const { return SubclassID; }
143 
144   enum ResolverTy GetResolverTy() {
145     if (SubclassID > ResolverTy::LastKnownResolverType)
146       return ResolverTy::UnknownResolver;
147     else
148       return (enum ResolverTy)SubclassID;
149   }
150 
151   const char *GetResolverName() { return ResolverTyToName(GetResolverTy()); }
152 
153   static const char *ResolverTyToName(enum ResolverTy);
154 
155   static ResolverTy NameToResolverTy(llvm::StringRef name);
156 
157   virtual lldb::BreakpointResolverSP
158   CopyForBreakpoint(Breakpoint &breakpoint) = 0;
159 
160 protected:
161   // Used for serializing resolver options:
162   // The options in this enum and the strings in the g_option_names must be
163   // kept in sync.
164   enum class OptionNames : uint32_t {
165     AddressOffset = 0,
166     ExactMatch,
167     FileName,
168     Inlines,
169     LanguageName,
170     LineNumber,
171     Column,
172     ModuleName,
173     NameMaskArray,
174     Offset,
175     PythonClassName,
176     RegexString,
177     ScriptArgs,
178     SectionName,
179     SearchDepth,
180     SkipPrologue,
181     SymbolNameArray,
182     LastOptionName
183   };
184   static const char
185       *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)];
186 
187   virtual void NotifyBreakpointSet() {};
188 
189 public:
190   static const char *GetKey(OptionNames enum_value) {
191     return g_option_names[static_cast<uint32_t>(enum_value)];
192   }
193 
194 protected:
195   /// Takes a symbol context list of matches which supposedly represent the
196   /// same file and line number in a CU, and find the nearest actual line
197   /// number that matches, and then filter down the matching addresses to
198   /// unique entries, and skip the prologue if asked to do so, and then set
199   /// breakpoint locations in this breakpoint for all the resultant addresses.
200   /// When \p column is nonzero the \p line and \p column args are used to
201   /// filter the results to find the first breakpoint >= (line, column).
202   void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list,
203                           bool skip_prologue, llvm::StringRef log_ident,
204                           uint32_t line = 0, uint32_t column = 0);
205   void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool,
206                           const char *) = delete;
207 
208   lldb::BreakpointLocationSP AddLocation(Address loc_addr,
209                                          bool *new_location = nullptr);
210 
211   Breakpoint *m_breakpoint; // This is the breakpoint we add locations to.
212   lldb::addr_t m_offset;    // A random offset the user asked us to add to any
213                             // breakpoints we set.
214 
215 private:
216   /// Helper for \p SetSCMatchesByLine.
217   void AddLocation(SearchFilter &filter, const SymbolContext &sc,
218                    bool skip_prologue, llvm::StringRef log_ident);
219 
220   // Subclass identifier (for llvm isa/dyn_cast)
221   const unsigned char SubclassID;
222   DISALLOW_COPY_AND_ASSIGN(BreakpointResolver);
223 };
224 
225 } // namespace lldb_private
226 
227 #endif // liblldb_BreakpointResolver_h_
228