]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / include / lldb / Symbol / UnwindPlan.h
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
12 namespace 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
39 class UnwindPlan {
40 public:
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                     undefined,          // reg is not available, e.g. volatile reg
54                     same,               // 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() : 
63                 m_type(unspecified), 
64                 m_location() 
65             {
66             }
67     
68             bool
69             operator == (const RegisterLocation& rhs) const;
70     
71             bool
72             operator != (const RegisterLocation &rhs) const
73             {
74                 return !(*this == rhs);
75             }
76             
77             void 
78             SetUnspecified()
79             {
80                 m_type = unspecified;
81             }
82
83             void 
84             SetUndefined()
85             {
86                 m_type = undefined;
87             }
88     
89             void 
90             SetSame()
91             {
92                 m_type = same;
93             }
94     
95             bool 
96             IsSame () const 
97             { 
98                 return m_type == same; 
99             }
100
101             bool 
102             IsUnspecified () const
103             {
104                 return m_type == unspecified; 
105             }
106
107             bool 
108             IsCFAPlusOffset () const
109             {
110                 return m_type == isCFAPlusOffset; 
111             }
112
113             bool 
114             IsAtCFAPlusOffset () const
115             {
116                 return m_type == atCFAPlusOffset; 
117             }
118
119             bool
120             IsInOtherRegister () const
121             {
122                 return m_type == inOtherRegister; 
123             }
124
125             bool
126             IsAtDWARFExpression () const
127             {
128                 return m_type == atDWARFExpression; 
129             }
130
131             bool
132             IsDWARFExpression () const
133             { 
134                 return m_type == isDWARFExpression; 
135             }
136
137             void
138             SetAtCFAPlusOffset (int32_t offset)
139             {
140                 m_type = atCFAPlusOffset;
141                 m_location.offset = offset;
142             }
143     
144             void
145             SetIsCFAPlusOffset (int32_t offset)
146             {
147                 m_type = isCFAPlusOffset;
148                 m_location.offset = offset;
149             }
150     
151             void 
152             SetInRegister (uint32_t reg_num)
153             {
154                 m_type = inOtherRegister;
155                 m_location.reg_num = reg_num;
156             }
157     
158             uint32_t
159             GetRegisterNumber () const
160             {
161                 if (m_type == inOtherRegister)
162                     return m_location.reg_num; 
163                 return LLDB_INVALID_REGNUM;
164             }
165
166             RestoreType
167             GetLocationType () const
168             {
169                 return m_type; 
170             }
171
172             int32_t
173             GetOffset () const
174             {
175                 if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
176                     return m_location.offset;
177                 return 0;
178             }
179             
180             void
181             GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const
182             {
183                 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
184                 {
185                     *opcodes = m_location.expr.opcodes; 
186                     len = m_location.expr.length; 
187                 }
188                 else
189                 {
190                     *opcodes = NULL;
191                     len = 0;
192                 }
193             }
194
195             void
196             SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len);
197     
198             void
199             SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
200
201             const uint8_t *
202             GetDWARFExpressionBytes () 
203             {
204                 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
205                     return m_location.expr.opcodes; 
206                 return NULL;
207             }
208
209             int
210             GetDWARFExpressionLength ()
211             {
212                 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
213                     return m_location.expr.length; 
214                 return 0;
215             }
216
217             void
218             Dump (Stream &s, 
219                   const UnwindPlan* unwind_plan, 
220                   const UnwindPlan::Row* row, 
221                   Thread* thread, 
222                   bool verbose) const;
223
224         private:
225             RestoreType m_type;            // How do we locate this register?
226             union
227             {
228                 // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
229                 int32_t offset;
230                 // For m_type == inOtherRegister
231                 uint32_t reg_num; // The register number
232                 // For m_type == atDWARFExpression or m_type == isDWARFExpression
233                 struct {
234                     const uint8_t *opcodes;
235                     uint16_t length;
236                 } expr;
237             } m_location;
238         };
239     
240     public:
241         Row ();
242     
243         Row (const UnwindPlan::Row& rhs) : 
244             m_offset             (rhs.m_offset),
245             m_cfa_reg_num        (rhs.m_cfa_reg_num),
246             m_cfa_offset         (rhs.m_cfa_offset),
247             m_register_locations (rhs.m_register_locations)
248         {
249         }
250
251         bool
252         operator == (const Row &rhs) const;
253
254         bool
255         GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
256     
257         void
258         SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location);
259     
260         lldb::addr_t
261         GetOffset() const
262         {
263             return m_offset;
264         }
265
266         void
267         SetOffset(lldb::addr_t offset)
268         {
269             m_offset = offset;
270         }
271
272         void
273         SlideOffset(lldb::addr_t offset)
274         {
275             m_offset += offset;
276         }
277
278         uint32_t
279         GetCFARegister () const
280         {
281             return m_cfa_reg_num;
282         }
283         
284         bool
285         SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, 
286                                               int32_t offset, 
287                                               bool can_replace);
288
289         bool
290         SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, 
291                                               int32_t offset, 
292                                               bool can_replace);
293
294         bool
295         SetRegisterLocationToUndefined (uint32_t reg_num, 
296                                         bool can_replace, 
297                                         bool can_replace_only_if_unspecified);
298
299         bool
300         SetRegisterLocationToUnspecified (uint32_t reg_num, 
301                                           bool can_replace);
302
303         bool
304         SetRegisterLocationToRegister (uint32_t reg_num, 
305                                        uint32_t other_reg_num,
306                                        bool can_replace);
307
308         bool
309         SetRegisterLocationToSame (uint32_t reg_num, 
310                                    bool must_replace);
311
312
313
314         void
315         SetCFARegister (uint32_t reg_num);
316
317         int32_t
318         GetCFAOffset () const
319         {
320             return m_cfa_offset;
321         }
322
323         void
324         SetCFAOffset (int32_t offset)
325         {
326             m_cfa_offset = offset;
327         }
328
329         void
330         Clear ();
331
332         void
333         Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const;
334
335     protected:
336         typedef std::map<uint32_t, RegisterLocation> collection;
337         lldb::addr_t m_offset;      // Offset into the function for this row
338         uint32_t m_cfa_reg_num;     // The Call Frame Address register number
339         int32_t  m_cfa_offset;      // The offset from the CFA for this row
340         collection m_register_locations;
341     }; // class Row
342
343 public:
344
345     typedef std::shared_ptr<Row> RowSP;
346
347     UnwindPlan (lldb::RegisterKind reg_kind) : 
348         m_row_list (), 
349         m_plan_valid_address_range (), 
350         m_register_kind (reg_kind), 
351         m_return_addr_register (LLDB_INVALID_REGNUM),
352         m_source_name (),
353         m_plan_is_sourced_from_compiler (eLazyBoolCalculate),
354         m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate)
355     {
356     }
357
358     ~UnwindPlan ()
359         {
360         }
361
362     void 
363     Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const;
364
365     void 
366     AppendRow (const RowSP& row_sp);
367
368     // Returns a pointer to the best row for the given offset into the function's instructions.
369     // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned.
370     // In practice, the UnwindPlan for a function with no known start address will be the architectural default
371     // UnwindPlan which will only have one row.
372     UnwindPlan::RowSP
373     GetRowForFunctionOffset (int offset) const;
374
375     lldb::RegisterKind
376     GetRegisterKind () const
377     {
378         return m_register_kind;
379     }
380
381     void
382     SetRegisterKind (lldb::RegisterKind kind)
383     {
384         m_register_kind = kind;
385     }
386     
387     void
388     SetReturnAddressRegister (uint32_t regnum)
389     {
390         m_return_addr_register = regnum;
391     }
392     
393     uint32_t
394     GetReturnAddressRegister (void)
395     {
396         return m_return_addr_register;
397     }
398
399     uint32_t
400     GetInitialCFARegister () const
401     {
402         if (m_row_list.empty())
403             return LLDB_INVALID_REGNUM;
404         return m_row_list.front()->GetCFARegister();
405     }
406
407     // This UnwindPlan may not be valid at every address of the function span.  
408     // For instance, a FastUnwindPlan will not be valid at the prologue setup 
409     // instructions - only in the body of the function.
410     void
411     SetPlanValidAddressRange (const AddressRange& range);
412
413     const AddressRange &
414     GetAddressRange () const
415     {
416         return m_plan_valid_address_range;
417     }
418
419     bool
420     PlanValidAtAddress (Address addr);
421
422     bool
423     IsValidRowIndex (uint32_t idx) const;
424
425     const UnwindPlan::RowSP
426     GetRowAtIndex (uint32_t idx) const;
427
428     const UnwindPlan::RowSP
429     GetLastRow () const;
430
431     lldb_private::ConstString
432     GetSourceName () const;
433
434     void
435     SetSourceName (const char *);
436
437     // Was this UnwindPlan emitted by a compiler?
438     lldb_private::LazyBool
439     GetSourcedFromCompiler () const
440     {
441         return m_plan_is_sourced_from_compiler;
442     }
443
444     // Was this UnwindPlan emitted by a compiler?
445     void
446     SetSourcedFromCompiler (lldb_private::LazyBool from_compiler)
447     {
448         m_plan_is_sourced_from_compiler = from_compiler;
449     }
450
451     // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
452     // e.g. for exception handling.
453     lldb_private::LazyBool
454     GetUnwindPlanValidAtAllInstructions () const
455     {
456         return m_plan_is_valid_at_all_instruction_locations;
457     }
458
459     // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
460     // e.g. for exception handling.
461     void
462     SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn)
463     {
464         m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
465     }
466
467     int
468     GetRowCount () const;
469
470     void
471     Clear()
472     {
473         m_row_list.clear();
474         m_plan_valid_address_range.Clear();
475         m_register_kind = lldb::eRegisterKindDWARF;
476         m_source_name.Clear();
477     }
478
479     const RegisterInfo *
480     GetRegisterInfo (Thread* thread, uint32_t reg_num) const;
481
482 private:
483
484     
485     typedef std::vector<RowSP> collection;
486     collection m_row_list;
487     AddressRange m_plan_valid_address_range;
488     lldb::RegisterKind m_register_kind;   // The RegisterKind these register numbers are in terms of - will need to be
489                                           // translated to lldb native reg nums at unwind time
490     uint32_t m_return_addr_register;      // The register that has the return address for the caller frame
491                                           // e.g. the lr on arm
492     lldb_private::ConstString m_source_name;  // for logging, where this UnwindPlan originated from
493     lldb_private::LazyBool m_plan_is_sourced_from_compiler;
494     lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
495 }; // class UnwindPlan
496
497 } // namespace lldb_private
498
499 #endif //liblldb_UnwindPlan_h