1 | #ifndef LLDB_SYMBOL_FUNCUNWINDERS_H |
2 | #define LLDB_SYMBOL_FUNCUNWINDERS_H |
3 | |
4 | #include "lldb/Core/AddressRange.h" |
5 | #include "lldb/lldb-private-enumerations.h" |
6 | #include <mutex> |
7 | #include <vector> |
8 | |
9 | namespace lldb_private { |
10 | |
11 | class UnwindTable; |
12 | |
13 | class FuncUnwinders { |
14 | public: |
15 | // FuncUnwinders objects are used to track UnwindPlans for a function (named |
16 | // or not - really just an address range) |
17 | |
18 | // We'll record four different UnwindPlans for each address range: |
19 | // |
20 | // 1. Unwinding from a call site (a valid exception throw location) |
21 | // This is often sourced from the eh_frame exception handling info |
22 | // 2. Unwinding from a non-call site (any location in the function) |
23 | // This is often done by analyzing the function prologue assembly |
24 | // language instructions |
25 | // 3. A fast unwind method for this function which only retrieves a |
26 | // limited set of registers necessary to walk the stack |
27 | // 4. An architectural default unwind plan when none of the above are |
28 | // available for some reason. |
29 | |
30 | // Additionally, FuncUnwinds object can be asked where the prologue |
31 | // instructions are finished for migrating breakpoints past the stack frame |
32 | // setup instructions when we don't have line table information. |
33 | |
34 | FuncUnwinders(lldb_private::UnwindTable &unwind_table, AddressRange range); |
35 | |
36 | ~FuncUnwinders(); |
37 | |
38 | lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread); |
39 | |
40 | lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target, |
41 | lldb_private::Thread &thread); |
42 | |
43 | lldb::UnwindPlanSP GetUnwindPlanFastUnwind(Target &target, |
44 | lldb_private::Thread &thread); |
45 | |
46 | lldb::UnwindPlanSP |
47 | GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread); |
48 | |
49 | lldb::UnwindPlanSP |
50 | GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread); |
51 | |
52 | Address &GetFirstNonPrologueInsn(Target &target); |
53 | |
54 | const Address &GetFunctionStartAddress() const; |
55 | |
56 | bool ContainsAddress(const Address &addr) const { |
57 | return m_range.ContainsFileAddress(so_addr: addr); |
58 | } |
59 | |
60 | // A function may have a Language Specific Data Area specified -- a block of |
61 | // data in |
62 | // the object file which is used in the processing of an exception throw / |
63 | // catch. If any of the UnwindPlans have the address of the LSDA region for |
64 | // this function, this will return it. |
65 | Address GetLSDAAddress(Target &target); |
66 | |
67 | // A function may have a Personality Routine associated with it -- used in the |
68 | // processing of throwing an exception. If any of the UnwindPlans have the |
69 | // address of the personality routine, this will return it. Read the target- |
70 | // pointer at this address to get the personality function address. |
71 | Address GetPersonalityRoutinePtrAddress(Target &target); |
72 | |
73 | // The following methods to retrieve specific unwind plans should rarely be |
74 | // used. Instead, clients should ask for the *behavior* they are looking for, |
75 | // using one of the above UnwindPlan retrieval methods. |
76 | |
77 | lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread); |
78 | |
79 | lldb::UnwindPlanSP GetObjectFileUnwindPlan(Target &target); |
80 | |
81 | lldb::UnwindPlanSP GetObjectFileAugmentedUnwindPlan(Target &target, |
82 | Thread &thread); |
83 | |
84 | lldb::UnwindPlanSP GetEHFrameUnwindPlan(Target &target); |
85 | |
86 | lldb::UnwindPlanSP GetEHFrameAugmentedUnwindPlan(Target &target, |
87 | Thread &thread); |
88 | |
89 | lldb::UnwindPlanSP GetDebugFrameUnwindPlan(Target &target); |
90 | |
91 | lldb::UnwindPlanSP GetDebugFrameAugmentedUnwindPlan(Target &target, |
92 | Thread &thread); |
93 | |
94 | lldb::UnwindPlanSP GetCompactUnwindUnwindPlan(Target &target); |
95 | |
96 | lldb::UnwindPlanSP GetArmUnwindUnwindPlan(Target &target); |
97 | |
98 | lldb::UnwindPlanSP GetSymbolFileUnwindPlan(Thread &thread); |
99 | |
100 | lldb::UnwindPlanSP GetArchDefaultUnwindPlan(Thread &thread); |
101 | |
102 | lldb::UnwindPlanSP GetArchDefaultAtFuncEntryUnwindPlan(Thread &thread); |
103 | |
104 | private: |
105 | lldb::UnwindAssemblySP GetUnwindAssemblyProfiler(Target &target); |
106 | |
107 | // Do a simplistic comparison for the register restore rule for getting the |
108 | // caller's pc value on two UnwindPlans -- returns LazyBoolYes if they have |
109 | // the same unwind rule for the pc, LazyBoolNo if they do not have the same |
110 | // unwind rule for the pc, and LazyBoolCalculate if it was unable to |
111 | // determine this for some reason. |
112 | lldb_private::LazyBool CompareUnwindPlansForIdenticalInitialPCLocation( |
113 | Thread &thread, const lldb::UnwindPlanSP &a, const lldb::UnwindPlanSP &b); |
114 | |
115 | UnwindTable &m_unwind_table; |
116 | AddressRange m_range; |
117 | |
118 | std::recursive_mutex m_mutex; |
119 | |
120 | lldb::UnwindPlanSP m_unwind_plan_assembly_sp; |
121 | lldb::UnwindPlanSP m_unwind_plan_object_file_sp; |
122 | lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp; |
123 | lldb::UnwindPlanSP m_unwind_plan_debug_frame_sp; |
124 | |
125 | // augmented by assembly inspection so it's valid everywhere |
126 | lldb::UnwindPlanSP m_unwind_plan_object_file_augmented_sp; |
127 | lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp; |
128 | lldb::UnwindPlanSP m_unwind_plan_debug_frame_augmented_sp; |
129 | |
130 | std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind; |
131 | lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp; |
132 | lldb::UnwindPlanSP m_unwind_plan_symbol_file_sp; |
133 | lldb::UnwindPlanSP m_unwind_plan_fast_sp; |
134 | lldb::UnwindPlanSP m_unwind_plan_arch_default_sp; |
135 | lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp; |
136 | |
137 | // Fetching the UnwindPlans can be expensive - if we've already attempted to |
138 | // get one & failed, don't try again. |
139 | bool m_tried_unwind_plan_assembly : 1, m_tried_unwind_plan_eh_frame : 1, |
140 | m_tried_unwind_plan_object_file : 1, |
141 | m_tried_unwind_plan_debug_frame : 1, |
142 | m_tried_unwind_plan_object_file_augmented : 1, |
143 | m_tried_unwind_plan_eh_frame_augmented : 1, |
144 | m_tried_unwind_plan_debug_frame_augmented : 1, |
145 | m_tried_unwind_plan_compact_unwind : 1, |
146 | m_tried_unwind_plan_arm_unwind : 1, m_tried_unwind_plan_symbol_file : 1, |
147 | m_tried_unwind_fast : 1, m_tried_unwind_arch_default : 1, |
148 | m_tried_unwind_arch_default_at_func_entry : 1; |
149 | |
150 | Address m_first_non_prologue_insn; |
151 | |
152 | FuncUnwinders(const FuncUnwinders &) = delete; |
153 | const FuncUnwinders &operator=(const FuncUnwinders &) = delete; |
154 | |
155 | }; // class FuncUnwinders |
156 | |
157 | } // namespace lldb_private |
158 | |
159 | #endif // LLDB_SYMBOL_FUNCUNWINDERS_H |
160 | |