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