1061da546Spatrick //===-- AppleThreadPlanStepThroughObjCTrampoline.h --------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLETHREADPLANSTEPTHROUGHOBJCTRAMPOLINE_H
10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLETHREADPLANSTEPTHROUGHOBJCTRAMPOLINE_H
11061da546Spatrick 
12061da546Spatrick #include "AppleObjCTrampolineHandler.h"
13061da546Spatrick #include "lldb/Core/Value.h"
14061da546Spatrick #include "lldb/Target/ThreadPlan.h"
15dda28197Spatrick #include "lldb/Target/ThreadPlanStepInRange.h"
16dda28197Spatrick #include "lldb/Target/ThreadPlanStepOut.h"
17dda28197Spatrick #include "lldb/Target/ThreadPlanShouldStopHere.h"
18061da546Spatrick #include "lldb/lldb-enumerations.h"
19061da546Spatrick #include "lldb/lldb-types.h"
20061da546Spatrick 
21061da546Spatrick namespace lldb_private {
22061da546Spatrick 
23061da546Spatrick class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan {
24061da546Spatrick public:
25061da546Spatrick   AppleThreadPlanStepThroughObjCTrampoline(
26dda28197Spatrick       Thread &thread, AppleObjCTrampolineHandler &trampoline_handler,
27*f6aab3d8Srobert       ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
28*f6aab3d8Srobert       lldb::addr_t sel_str_addr, llvm::StringRef sel_str);
29061da546Spatrick 
30061da546Spatrick   ~AppleThreadPlanStepThroughObjCTrampoline() override;
31061da546Spatrick 
32061da546Spatrick   static bool PreResumeInitializeFunctionCaller(void *myself);
33061da546Spatrick 
34061da546Spatrick   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
35061da546Spatrick 
36061da546Spatrick   bool ValidatePlan(Stream *error) override;
37061da546Spatrick 
38061da546Spatrick   lldb::StateType GetPlanRunState() override;
39061da546Spatrick 
40061da546Spatrick   bool ShouldStop(Event *event_ptr) override;
41061da546Spatrick 
42be691f3bSpatrick   // The step through code might have to fill in the cache, so it is not safe
43be691f3bSpatrick   // to run only one thread.
StopOthers()44be691f3bSpatrick   bool StopOthers() override { return false; }
45061da546Spatrick 
46061da546Spatrick   // The base class MischiefManaged does some cleanup - so you have to call it
47061da546Spatrick   // in your MischiefManaged derived class.
48061da546Spatrick   bool MischiefManaged() override;
49061da546Spatrick 
50061da546Spatrick   void DidPush() override;
51061da546Spatrick 
52061da546Spatrick   bool WillStop() override;
53061da546Spatrick 
54061da546Spatrick protected:
55061da546Spatrick   bool DoPlanExplainsStop(Event *event_ptr) override;
56061da546Spatrick 
57061da546Spatrick private:
58061da546Spatrick   bool InitializeFunctionCaller();
59061da546Spatrick 
60dda28197Spatrick   AppleObjCTrampolineHandler &m_trampoline_handler; /// The handler itself.
61dda28197Spatrick   lldb::addr_t m_args_addr; /// Stores the address for our step through function
62dda28197Spatrick                             /// result structure.
63061da546Spatrick   ValueList m_input_values;
64dda28197Spatrick   lldb::addr_t m_isa_addr; /// isa_addr and sel_addr are the keys we will use to
65dda28197Spatrick                            /// cache the implementation.
66061da546Spatrick   lldb::addr_t m_sel_addr;
67dda28197Spatrick   lldb::ThreadPlanSP m_func_sp; /// This is the function call plan.  We fill it
68dda28197Spatrick                                 /// at start, then set it to NULL when this plan
69dda28197Spatrick                                 /// is done.  That way we know to go on to:
70dda28197Spatrick   lldb::ThreadPlanSP m_run_to_sp;  /// The plan that runs to the target.
71dda28197Spatrick   FunctionCaller *m_impl_function; /// This is a pointer to a impl function that
72dda28197Spatrick                                    /// is owned by the client that pushes this
73dda28197Spatrick                                    /// plan.
74*f6aab3d8Srobert   lldb::addr_t m_sel_str_addr; /// If this is not LLDB_INVALID_ADDRESS then it
75*f6aab3d8Srobert                                /// is the address we wrote the selector string
76*f6aab3d8Srobert                                /// to.  We need to deallocate it when the
77*f6aab3d8Srobert                                /// function call is done.
78*f6aab3d8Srobert   std::string m_sel_str;       /// This is the string we wrote to memory - we
79*f6aab3d8Srobert                                /// use it for caching, but only if
80*f6aab3d8Srobert                                /// m_sel_str_addr is non-null.
81dda28197Spatrick };
82dda28197Spatrick 
83dda28197Spatrick class AppleThreadPlanStepThroughDirectDispatch: public ThreadPlanStepOut {
84dda28197Spatrick public:
85be691f3bSpatrick   AppleThreadPlanStepThroughDirectDispatch(Thread &thread,
86be691f3bSpatrick                                            AppleObjCTrampolineHandler &handler,
87be691f3bSpatrick                                            llvm::StringRef dispatch_func_name);
88dda28197Spatrick 
89dda28197Spatrick   ~AppleThreadPlanStepThroughDirectDispatch() override;
90dda28197Spatrick 
91dda28197Spatrick   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
92dda28197Spatrick 
93dda28197Spatrick   bool ShouldStop(Event *event_ptr) override;
94dda28197Spatrick 
StopOthers()95be691f3bSpatrick   bool StopOthers() override { return false; }
96dda28197Spatrick 
97dda28197Spatrick   bool MischiefManaged() override;
98dda28197Spatrick 
99dda28197Spatrick   bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
100dda28197Spatrick 
SetFlagsToDefault()101dda28197Spatrick   void SetFlagsToDefault() override {
102dda28197Spatrick           GetFlags().Set(ThreadPlanStepInRange::GetDefaultFlagsValue());
103dda28197Spatrick   }
104dda28197Spatrick 
105dda28197Spatrick protected:
106dda28197Spatrick   bool DoPlanExplainsStop(Event *event_ptr) override;
107dda28197Spatrick 
108dda28197Spatrick   AppleObjCTrampolineHandler &m_trampoline_handler;
109dda28197Spatrick   std::string m_dispatch_func_name;  /// Which dispatch function we're stepping
110dda28197Spatrick                                      /// through.
111dda28197Spatrick   lldb::ThreadPlanSP m_objc_step_through_sp; /// When we hit an objc_msgSend,
112dda28197Spatrick                                              /// we'll use this plan to get to
113dda28197Spatrick                                              /// its target.
114dda28197Spatrick   std::vector<lldb::BreakpointSP> m_msgSend_bkpts; /// Breakpoints on the objc
115dda28197Spatrick                                                    /// dispatch functions.
116dda28197Spatrick   bool m_at_msg_send;  /// Are we currently handling an msg_send
117dda28197Spatrick 
118061da546Spatrick };
119061da546Spatrick 
120061da546Spatrick } // namespace lldb_private
121061da546Spatrick 
122dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLETHREADPLANSTEPTHROUGHOBJCTRAMPOLINE_H
123