1 #ifndef liblldb_FuncUnwinders_h
2 #define liblldb_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(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   DISALLOW_COPY_AND_ASSIGN(FuncUnwinders);
153 
154 }; // class FuncUnwinders
155 
156 } // namespace lldb_private
157 
158 #endif // liblldb_FuncUnwinders_h
159