UnwindPlan.h revision 8e69de4b9c55ec2eaebc62e4d987c2f0618ac431
1#ifndef liblldb_UnwindPlan_h
2#define liblldb_UnwindPlan_h
3
4#include "lldb/lldb-private.h"
5#include "lldb/Core/AddressRange.h"
6#include "lldb/Core/Stream.h"
7#include "lldb/Core/ConstString.h"
8
9#include <map>
10#include <vector>
11
12namespace lldb_private {
13
14// The UnwindPlan object specifies how to unwind out of a function - where
15// this function saves the caller's register values before modifying them
16// (for non-volatile aka saved registers) and how to find this frame's
17// Canonical Frame Address (CFA).
18
19// Most commonly, registers are saved on the stack, offset some bytes from
20// the Canonical Frame Address, or CFA, which is the starting address of
21// this function's stack frame (the CFA is same as the eh_frame's CFA,
22// whatever that may be on a given architecture).
23// The CFA address for the stack frame does not change during
24// the lifetime of the function.
25
26// Internally, the UnwindPlan is structured as a vector of register locations
27// organized by code address in the function, showing which registers have been
28// saved at that point and where they are saved.
29// It can be thought of as the expanded table form of the DWARF CFI
30// encoded information.
31
32// Other unwind information sources will be converted into UnwindPlans before
33// being added to a FuncUnwinders object.  The unwind source may be
34// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based
35// prologue analysis.
36// The UnwindPlan is the canonical form of this information that the unwinder
37// code will use when walking the stack.
38
39class UnwindPlan {
40public:
41
42    class Row {
43    public:
44        class RegisterLocation
45        {
46        public:
47
48            enum RestoreType
49                {
50                    unspecified,        // not specified, we may be able to assume this
51                                        // is the same register. gcc doesn't specify all
52                                        // initial values so we really don't know...
53                    isUndefined,        // reg is not available, e.g. volatile reg
54                    isSame,             // reg is unchanged
55                    atCFAPlusOffset,    // reg = deref(CFA + offset)
56                    isCFAPlusOffset,    // reg = CFA + offset
57                    inOtherRegister,    // reg = other reg
58                    atDWARFExpression,  // reg = deref(eval(dwarf_expr))
59                    isDWARFExpression   // reg = eval(dwarf_expr)
60                };
61
62            RegisterLocation() : m_type(unspecified), m_location() { }
63
64            bool
65            operator == (const RegisterLocation& rhs) const;
66
67            void SetUnspecified();
68
69            void SetUndefined();
70
71            void SetSame();
72
73            bool IsSame () const { return m_type == isSame; }
74
75            bool IsUnspecified () const { return m_type == unspecified; }
76
77            bool IsCFAPlusOffset () const { return m_type == isCFAPlusOffset; }
78
79            bool IsAtCFAPlusOffset () const { return m_type == atCFAPlusOffset; }
80
81            bool IsInOtherRegister () const { return m_type == inOtherRegister; }
82
83            bool IsAtDWARFExpression () const { return m_type == atDWARFExpression; }
84
85            bool IsDWARFExpression () const { return m_type == isDWARFExpression; }
86
87            void SetAtCFAPlusOffset (int32_t offset);
88
89            void SetIsCFAPlusOffset (int32_t offset);
90
91            void SetInRegister (uint32_t reg_num);
92
93            uint32_t GetRegisterNumber () const { return m_location.reg_num; }
94
95            RestoreType GetLocationType () const { return m_type; }
96
97            int32_t GetOffset () const { return m_location.offset; }
98
99            void GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const { *opcodes = m_location.expr.opcodes; len = m_location.expr.length; }
100
101            void
102            SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len);
103
104            void
105            SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
106
107            const uint8_t *
108            GetDWARFExpressionBytes () { return m_location.expr.opcodes; }
109
110            int
111            GetDWARFExpressionLength () { return m_location.expr.length; }
112
113            void
114            Dump (Stream &s) const;
115
116        private:
117            RestoreType m_type;            // How do we locate this register?
118            union
119            {
120                // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
121                int32_t offset;
122                // For m_type == inOtherRegister
123                uint32_t reg_num; // The register number
124                // For m_type == atDWARFExpression or m_type == isDWARFExpression
125                struct {
126                    const uint8_t *opcodes;
127                    uint16_t length;
128                } expr;
129            } m_location;
130        };
131
132    public:
133        Row ();
134
135        bool
136        GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
137
138        void
139        SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location);
140
141        lldb::addr_t
142        GetOffset() const
143        {
144            return m_offset;
145        }
146
147        void
148        SetOffset(lldb::addr_t offset)
149        {
150            m_offset = offset;
151        }
152
153        void
154        SlideOffset(lldb::addr_t offset)
155        {
156            m_offset += offset;
157        }
158
159        uint32_t
160        GetCFARegister () const
161        {
162            return m_cfa_reg_num;
163        }
164
165        void
166        SetCFARegister (uint32_t reg_num)
167        {
168            m_cfa_reg_num = reg_num;
169        }
170
171        int32_t
172        GetCFAOffset () const
173        {
174            return m_cfa_offset;
175        }
176
177        void
178        SetCFAOffset (int32_t offset)
179        {
180            m_cfa_offset = offset;
181        }
182
183        // Return the number of registers we have locations for
184        int
185        GetRegisterCount () const
186        {
187            return m_register_locations.size();
188        }
189
190        void
191        Clear ();
192
193        void
194        Dump (Stream& s, int register_kind, Thread* thread) const;
195
196    protected:
197        typedef std::map<uint32_t, RegisterLocation> collection;
198        lldb::addr_t m_offset;      // Offset into the function for this row
199        uint32_t m_cfa_reg_num;     // The Call Frame Address register number
200        int32_t  m_cfa_offset;      // The offset from the CFA for this row
201        collection m_register_locations;
202
203    }; // class Row
204
205public:
206
207    UnwindPlan () : m_register_kind(-1), m_row_list(), m_plan_valid_address_range(), m_source_name()
208    {
209        m_plan_valid_address_range.SetByteSize (0);
210    }
211
212    void Dump (Stream& s, Thread* thread) const;
213
214    void
215    AppendRow (const Row& row);
216
217    // Returns a pointer to the best row for the given offset into the function's instructions.
218    // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned.
219    // In practice, the UnwindPlan for a function with no known start address will be the architectural default
220    // UnwindPlan which will only have one row.
221    const Row*
222    GetRowForFunctionOffset (int offset) const;
223
224    void
225    SetRegisterKind (uint32_t rk);
226
227    uint32_t
228    GetRegisterKind (void) const;
229
230    // This UnwindPlan may not be valid at every address of the function span.
231    // For instance, a FastUnwindPlan will not be valid at the prologue setup
232    // instructions - only in the body of the function.
233    void
234    SetPlanValidAddressRange (const AddressRange& range);
235
236    bool
237    PlanValidAtAddress (Address addr);
238
239    bool
240    IsValidRowIndex (uint32_t idx) const;
241
242    const UnwindPlan::Row&
243    GetRowAtIndex (uint32_t idx) const;
244
245    lldb_private::ConstString
246    GetSourceName () const;
247
248    void
249    SetSourceName (const char *);
250
251    int
252    GetRowCount () const;
253
254private:
255
256    typedef std::vector<Row> collection;
257    collection m_row_list;
258    AddressRange m_plan_valid_address_range;
259    uint32_t m_register_kind;   // The RegisterKind these register numbers are in terms of - will need to be
260                                // translated to lldb native reg nums at unwind time
261    lldb_private::ConstString m_source_name;  // for logging, where this UnwindPlan originated from
262}; // class UnwindPlan
263
264} // namespace lldb_private
265
266#endif //liblldb_UnwindPlan_h
267