aboutsummaryrefslogtreecommitdiff
path: root/include/lldb/Symbol/FuncUnwinders.h
blob: 0d4aabb5fd570a9ee089093553c8a12ef606f448 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef liblldb_FuncUnwinders_h
#define liblldb_FuncUnwinders_h

#include <vector>

#include "lldb/Core/AddressRange.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Host/Mutex.h"

namespace lldb_private {

class UnwindTable;

class FuncUnwinders 
{
public:
    // FuncUnwinders objects are used to track UnwindPlans for a function
    // (named or not - really just an address range)

    // We'll record four different UnwindPlans for each address range:
    //   
    //   1. Unwinding from a call site (a valid exception throw location)
    //      This is often sourced from the eh_frame exception handling info
    //   2. Unwinding from a non-call site (any location in the function)
    //      This is often done by analyzing the function prologue assembly
    //      language instructions
    //   3. A fast unwind method for this function which only retrieves a 
    //      limited set of registers necessary to walk the stack
    //   4. An architectural default unwind plan when none of the above are
    //      available for some reason.

    // Additionally, FuncUnwinds object can be asked where the prologue 
    // instructions are finished for migrating breakpoints past the 
    // stack frame setup instructions when we don't have line table information.

    FuncUnwinders (lldb_private::UnwindTable& unwind_table, AddressRange range);

    ~FuncUnwinders ();

    // current_offset is the byte offset into the function.
    // 0 means no instructions have executed yet.  -1 means the offset is unknown.
    // On architectures where the pc points to the next instruction that will execute, this
    // offset value will have already been decremented by 1 to stay within the bounds of the 
    // correct function body.
    lldb::UnwindPlanSP
    GetUnwindPlanAtCallSite (Target &target, int current_offset);

    lldb::UnwindPlanSP
    GetUnwindPlanAtNonCallSite (Target& target, lldb_private::Thread& thread, int current_offset);

    lldb::UnwindPlanSP
    GetUnwindPlanFastUnwind (Target& target, lldb_private::Thread& thread);

    lldb::UnwindPlanSP
    GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread);

    lldb::UnwindPlanSP
    GetUnwindPlanArchitectureDefaultAtFunctionEntry (lldb_private::Thread& thread);

    Address&
    GetFirstNonPrologueInsn (Target& target);

    const Address&
    GetFunctionStartAddress () const;

    bool
    ContainsAddress (const Address& addr) const
    { 
        return m_range.ContainsFileAddress (addr);
    }

    // A function may have a Language Specific Data Area specified -- a block of data in
    // the object file which is used in the processing of an exception throw / catch.
    // If any of the UnwindPlans have the address of the LSDA region for this function,
    // this will return it.  
    Address
    GetLSDAAddress (Target &target);

    // A function may have a Personality Routine associated with it -- used in the
    // processing of throwing an exception.  If any of the UnwindPlans have the
    // address of the personality routine, this will return it.  Read the target-pointer
    // at this address to get the personality function address.
    Address
    GetPersonalityRoutinePtrAddress (Target &target);



    // The following methods to retrieve specific unwind plans should rarely be used.
    // Instead, clients should ask for the *behavior* they are looking for, using one
    // of the above UnwindPlan retrieval methods.

    lldb::UnwindPlanSP
    GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset);

    lldb::UnwindPlanSP
    GetEHFrameUnwindPlan (Target &target, int current_offset);

    lldb::UnwindPlanSP
    GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset);

    lldb::UnwindPlanSP
    GetCompactUnwindUnwindPlan (Target &target, int current_offset);

    lldb::UnwindPlanSP
    GetArchDefaultUnwindPlan (Thread &thread);

    lldb::UnwindPlanSP
    GetArchDefaultAtFuncEntryUnwindPlan (Thread &thread);

private:

    lldb::UnwindAssemblySP
    GetUnwindAssemblyProfiler (Target& target);

    UnwindTable& m_unwind_table;
    AddressRange m_range;

    Mutex m_mutex;

    lldb::UnwindPlanSP              m_unwind_plan_assembly_sp;
    lldb::UnwindPlanSP              m_unwind_plan_eh_frame_sp;
    lldb::UnwindPlanSP              m_unwind_plan_eh_frame_augmented_sp;   // augmented by assembly inspection so it's valid everywhere
    std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind;
    lldb::UnwindPlanSP              m_unwind_plan_fast_sp;
    lldb::UnwindPlanSP              m_unwind_plan_arch_default_sp;
    lldb::UnwindPlanSP              m_unwind_plan_arch_default_at_func_entry_sp;

    // Fetching the UnwindPlans can be expensive - if we've already attempted
    // to get one & failed, don't try again.
    bool m_tried_unwind_plan_assembly:1,
         m_tried_unwind_plan_eh_frame:1,
         m_tried_unwind_plan_eh_frame_augmented:1,
         m_tried_unwind_plan_compact_unwind:1,
         m_tried_unwind_fast:1,
         m_tried_unwind_arch_default:1,
         m_tried_unwind_arch_default_at_func_entry:1;

    Address m_first_non_prologue_insn;

    DISALLOW_COPY_AND_ASSIGN (FuncUnwinders);

}; // class FuncUnwinders

} // namespace lldb_private


#endif //liblldb_FuncUnwinders_h