1 | //===-- AppleThreadPlanStepThroughObjCTrampoline.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 LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLETHREADPLANSTEPTHROUGHOBJCTRAMPOLINE_H |
10 | #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLETHREADPLANSTEPTHROUGHOBJCTRAMPOLINE_H |
11 | |
12 | #include "AppleObjCTrampolineHandler.h" |
13 | #include "lldb/Core/Value.h" |
14 | #include "lldb/Target/ThreadPlan.h" |
15 | #include "lldb/Target/ThreadPlanStepInRange.h" |
16 | #include "lldb/Target/ThreadPlanStepOut.h" |
17 | #include "lldb/Target/ThreadPlanShouldStopHere.h" |
18 | #include "lldb/lldb-enumerations.h" |
19 | #include "lldb/lldb-types.h" |
20 | |
21 | namespace lldb_private { |
22 | |
23 | class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan { |
24 | public: |
25 | AppleThreadPlanStepThroughObjCTrampoline( |
26 | Thread &thread, AppleObjCTrampolineHandler &trampoline_handler, |
27 | ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr, |
28 | lldb::addr_t sel_str_addr, llvm::StringRef sel_str); |
29 | |
30 | ~AppleThreadPlanStepThroughObjCTrampoline() override; |
31 | |
32 | static bool PreResumeInitializeFunctionCaller(void *myself); |
33 | |
34 | void GetDescription(Stream *s, lldb::DescriptionLevel level) override; |
35 | |
36 | bool ValidatePlan(Stream *error) override; |
37 | |
38 | lldb::StateType GetPlanRunState() override; |
39 | |
40 | bool ShouldStop(Event *event_ptr) override; |
41 | |
42 | // The step through code might have to fill in the cache, so it is not safe |
43 | // to run only one thread. |
44 | bool StopOthers() override { return false; } |
45 | |
46 | // The base class MischiefManaged does some cleanup - so you have to call it |
47 | // in your MischiefManaged derived class. |
48 | bool MischiefManaged() override; |
49 | |
50 | void DidPush() override; |
51 | |
52 | bool WillStop() override; |
53 | |
54 | protected: |
55 | bool DoPlanExplainsStop(Event *event_ptr) override; |
56 | |
57 | private: |
58 | bool InitializeFunctionCaller(); |
59 | |
60 | AppleObjCTrampolineHandler &m_trampoline_handler; /// The handler itself. |
61 | lldb::addr_t m_args_addr; /// Stores the address for our step through function |
62 | /// result structure. |
63 | ValueList m_input_values; |
64 | lldb::addr_t m_isa_addr; /// isa_addr and sel_addr are the keys we will use to |
65 | /// cache the implementation. |
66 | lldb::addr_t m_sel_addr; |
67 | lldb::ThreadPlanSP m_func_sp; /// This is the function call plan. We fill it |
68 | /// at start, then set it to NULL when this plan |
69 | /// is done. That way we know to go on to: |
70 | lldb::ThreadPlanSP m_run_to_sp; /// The plan that runs to the target. |
71 | FunctionCaller *m_impl_function; /// This is a pointer to a impl function that |
72 | /// is owned by the client that pushes this |
73 | /// plan. |
74 | lldb::addr_t m_sel_str_addr; /// If this is not LLDB_INVALID_ADDRESS then it |
75 | /// is the address we wrote the selector string |
76 | /// to. We need to deallocate it when the |
77 | /// function call is done. |
78 | std::string m_sel_str; /// This is the string we wrote to memory - we |
79 | /// use it for caching, but only if |
80 | /// m_sel_str_addr is non-null. |
81 | }; |
82 | |
83 | class AppleThreadPlanStepThroughDirectDispatch: public ThreadPlanStepOut { |
84 | public: |
85 | AppleThreadPlanStepThroughDirectDispatch(Thread &thread, |
86 | AppleObjCTrampolineHandler &handler, |
87 | llvm::StringRef dispatch_func_name); |
88 | |
89 | ~AppleThreadPlanStepThroughDirectDispatch() override; |
90 | |
91 | void GetDescription(Stream *s, lldb::DescriptionLevel level) override; |
92 | |
93 | bool ShouldStop(Event *event_ptr) override; |
94 | |
95 | bool StopOthers() override { return false; } |
96 | |
97 | bool MischiefManaged() override; |
98 | |
99 | bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; |
100 | |
101 | void SetFlagsToDefault() override { |
102 | GetFlags().Set(ThreadPlanStepInRange::GetDefaultFlagsValue()); |
103 | } |
104 | |
105 | protected: |
106 | bool DoPlanExplainsStop(Event *event_ptr) override; |
107 | |
108 | AppleObjCTrampolineHandler &m_trampoline_handler; |
109 | std::string m_dispatch_func_name; /// Which dispatch function we're stepping |
110 | /// through. |
111 | lldb::ThreadPlanSP m_objc_step_through_sp; /// When we hit an objc_msgSend, |
112 | /// we'll use this plan to get to |
113 | /// its target. |
114 | std::vector<lldb::BreakpointSP> m_msgSend_bkpts; /// Breakpoints on the objc |
115 | /// dispatch functions. |
116 | bool m_at_msg_send; /// Are we currently handling an msg_send |
117 | |
118 | }; |
119 | |
120 | } // namespace lldb_private |
121 | |
122 | #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLETHREADPLANSTEPTHROUGHOBJCTRAMPOLINE_H |
123 | |