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
9namespace lldb_private {
10
11class UnwindTable;
12
13class FuncUnwinders {
14public:
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
104private:
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