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
//===-- ThreadPlanShouldStopHere.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_ThreadPlanShouldStopHere_h_
#define liblldb_ThreadPlanShouldStopHere_h_

#include "lldb/Target/ThreadPlan.h"

namespace lldb_private {

// This is an interface that ThreadPlans can adopt to allow flexible
// modifications of the behavior when a thread plan comes to a place where it
// would ordinarily stop.  If such modification makes sense for your plan,
// inherit from this class, and when you would be about to stop (in your
// ShouldStop method), call InvokeShouldStopHereCallback, passing in the frame
// comparison between where the step operation started and where you arrived.
// If it returns true, then QueueStepOutFromHere will queue the plan to execute
// instead of stopping.
//
// The classic example of the use of this is ThreadPlanStepInRange not stopping
// in frames that have no debug information.
//
// This class also defines a set of flags to control general aspects of this
// "ShouldStop" behavior.
// A class implementing this protocol needs to define a default set of flags,
// and can provide access to
// changing that default flag set if it wishes.

class ThreadPlanShouldStopHere {
public:
  struct ThreadPlanShouldStopHereCallbacks {
    ThreadPlanShouldStopHereCallbacks() {
      should_stop_here_callback = nullptr;
      step_from_here_callback = nullptr;
    }

    ThreadPlanShouldStopHereCallbacks(
        ThreadPlanShouldStopHereCallback should_stop,
        ThreadPlanStepFromHereCallback step_from_here) {
      should_stop_here_callback = should_stop;
      step_from_here_callback = step_from_here;
    }

    void Clear() {
      should_stop_here_callback = nullptr;
      step_from_here_callback = nullptr;
    }

    ThreadPlanShouldStopHereCallback should_stop_here_callback;
    ThreadPlanStepFromHereCallback step_from_here_callback;
  };

  enum {
    eNone = 0,
    eAvoidInlines = (1 << 0),
    eStepInAvoidNoDebug = (1 << 1),
    eStepOutAvoidNoDebug = (1 << 2)
  };

  // Constructors and Destructors
  ThreadPlanShouldStopHere(ThreadPlan *owner);

  ThreadPlanShouldStopHere(ThreadPlan *owner,
                           const ThreadPlanShouldStopHereCallbacks *callbacks,
                           void *baton = nullptr);
  virtual ~ThreadPlanShouldStopHere();

  // Set the ShouldStopHere callbacks.  Pass in null to clear them and have no
  // special behavior (though you can also call ClearShouldStopHereCallbacks
  // for that purpose.  If you pass in a valid pointer, it will adopt the non-
  // null fields, and any null fields will be set to the default values.

  void
  SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks *callbacks,
                             void *baton) {
    if (callbacks) {
      m_callbacks = *callbacks;
      if (!m_callbacks.should_stop_here_callback)
        m_callbacks.should_stop_here_callback =
            ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
      if (!m_callbacks.step_from_here_callback)
        m_callbacks.step_from_here_callback =
            ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
    } else {
      ClearShouldStopHereCallbacks();
    }
    m_baton = baton;
  }

  void ClearShouldStopHereCallbacks() { m_callbacks.Clear(); }

  bool InvokeShouldStopHereCallback(lldb::FrameComparison operation,
                                    Status &status);

  lldb::ThreadPlanSP
  CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation,
                                     Status &status);

  lldb_private::Flags &GetFlags() { return m_flags; }

  const lldb_private::Flags &GetFlags() const { return m_flags; }

protected:
  static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan,
                                            Flags &flags,
                                            lldb::FrameComparison operation,
                                            Status &status, void *baton);

  static lldb::ThreadPlanSP
  DefaultStepFromHereCallback(ThreadPlan *current_plan, Flags &flags,
                              lldb::FrameComparison operation, Status &status,
                              void *baton);

  virtual lldb::ThreadPlanSP
  QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation,
                           Status &status);

  // Implement this, and call it in the plan's constructor to set the default
  // flags.
  virtual void SetFlagsToDefault() = 0;

  ThreadPlanShouldStopHereCallbacks m_callbacks;
  void *m_baton;
  ThreadPlan *m_owner;
  lldb_private::Flags m_flags;

private:
  DISALLOW_COPY_AND_ASSIGN(ThreadPlanShouldStopHere);
};

} // namespace lldb_private

#endif // liblldb_ThreadPlanShouldStopHere_h_