reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
//===-- BreakpointLocation.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 liblldb_BreakpointLocation_h_
#define liblldb_BreakpointLocation_h_

#include <memory>
#include <mutex>

#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/StoppointLocation.h"
#include "lldb/Core/Address.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

/// \class BreakpointLocation BreakpointLocation.h
/// "lldb/Breakpoint/BreakpointLocation.h" Class that manages one unique (by
/// address) instance of a logical breakpoint.

/// General Outline:
/// A breakpoint location is defined by the breakpoint that produces it,
/// and the address that resulted in this particular instantiation. Each
/// breakpoint location also may have a breakpoint site if its address has
/// been loaded into the program. Finally it has a settable options object.
///
/// FIXME: Should we also store some fingerprint for the location, so
/// we can map one location to the "equivalent location" on rerun?  This would
/// be useful if you've set options on the locations.

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 enabled 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;

  /// If \a auto_continue is \b true, set the breakpoint to continue when hit.
  void SetAutoContinue(bool auto_continue);

  /// Check the AutoContinue state.
  ///
  /// \return
  ///     \b true if the breakpoint is set to auto-continue, \b false if not.
  bool IsAutoContinue() 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, Status &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 return the options that have a setting for the specified
  /// BreakpointOptions kind.
  ///
  /// \param[in] kind
  ///     The particular option you are looking up.
  /// \return
  ///     A pointer to the containing breakpoint's options if this
  ///     location doesn't have its own copy.
  const BreakpointOptions *GetOptionsSpecifyingKind(
      BreakpointOptions::OptionKind kind) 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();

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_up; ///< 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

#endif // liblldb_BreakpointLocation_h_