aboutsummaryrefslogtreecommitdiff
path: root/lldb/include/lldb/Breakpoint/BreakpointResolver.h
blob: d067b1eea6fff6ed7d3d6337585657fbfa8cb597 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//===-- 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, uint32_t column = 0);
  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