]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
Update our copy of the Linux dts files to be in sync with Linux 4.5-rc1. We
[FreeBSD/FreeBSD.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         class CFAValue
241         {
242         public:
243
244             enum ValueType
245             {
246                 unspecified,                  // not specified
247                 isRegisterPlusOffset,         // CFA = register + offset
248                 isRegisterDereferenced,       // CFA = [reg]
249                 isDWARFExpression             // CFA = eval(dwarf_expr)
250             };
251
252             CFAValue() :
253                 m_type(unspecified),
254                 m_value()
255             {
256             }
257
258             bool
259             operator == (const CFAValue& rhs) const;
260
261             bool
262             operator != (const CFAValue &rhs) const
263             {
264                 return !(*this == rhs);
265             }
266
267             void
268             SetUnspecified()
269             {
270                 m_type = unspecified;
271             }
272
273             bool
274             IsUnspecified () const
275             {
276                 return m_type == unspecified;
277             }
278
279             bool
280             IsRegisterPlusOffset () const
281             {
282                 return m_type == isRegisterPlusOffset;
283             }
284
285             void
286             SetIsRegisterPlusOffset (uint32_t reg_num, int32_t offset)
287             {
288                 m_type = isRegisterPlusOffset;
289                 m_value.reg.reg_num = reg_num;
290                 m_value.reg.offset = offset;
291             }
292
293             bool
294             IsRegisterDereferenced () const
295             {
296                 return m_type == isRegisterDereferenced;
297             }
298
299             void
300             SetIsRegisterDereferenced (uint32_t reg_num)
301             {
302                 m_type = isRegisterDereferenced;
303                 m_value.reg.reg_num = reg_num;
304             }
305
306             bool
307             IsDWARFExpression () const
308             {
309                 return m_type == isDWARFExpression;
310             }
311
312             void
313             SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
314             {
315                 m_type = isDWARFExpression;
316                 m_value.expr.opcodes = opcodes;
317                 m_value.expr.length = len;
318             }
319
320             uint32_t
321             GetRegisterNumber () const
322             {
323                 if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset)
324                     return m_value.reg.reg_num;
325                 return LLDB_INVALID_REGNUM;
326             }
327
328             ValueType
329             GetValueType () const
330             {
331                 return m_type;
332             }
333
334             int32_t
335             GetOffset () const
336             {
337                 if (m_type == isRegisterPlusOffset)
338                     return m_value.reg.offset;
339                 return 0;
340             }
341
342             void IncOffset (int32_t delta)
343             {
344                 if (m_type == isRegisterPlusOffset)
345                     m_value.reg.offset += delta;
346             }
347
348             void SetOffset (int32_t offset)
349             {
350                 if (m_type == isRegisterPlusOffset)
351                     m_value.reg.offset = offset;
352             }
353
354             void
355             GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const
356             {
357                 if (m_type == isDWARFExpression)
358                 {
359                     *opcodes = m_value.expr.opcodes;
360                     len = m_value.expr.length;
361                 }
362                 else
363                 {
364                     *opcodes = NULL;
365                     len = 0;
366                 }
367             }
368
369             const uint8_t *
370             GetDWARFExpressionBytes ()
371             {
372                 if (m_type == isDWARFExpression)
373                     return m_value.expr.opcodes;
374                 return NULL;
375             }
376
377             int
378             GetDWARFExpressionLength ()
379             {
380                 if (m_type == isDWARFExpression)
381                     return m_value.expr.length;
382                 return 0;
383             }
384
385             void
386             Dump (Stream &s,
387                   const UnwindPlan* unwind_plan,
388                   Thread* thread) const;
389
390         private:
391             ValueType m_type;            // How do we compute CFA value?
392             union
393             {
394                 struct {
395                     // For m_type == isRegisterPlusOffset or m_type == isRegisterDereferenced
396                     uint32_t reg_num; // The register number
397                     // For m_type == isRegisterPlusOffset
398                     int32_t offset;
399                 } reg;
400                 // For m_type == isDWARFExpression
401                 struct {
402                     const uint8_t *opcodes;
403                     uint16_t length;
404                 } expr;
405             } m_value;
406         }; // class CFAValue
407
408     public:
409         Row ();
410
411         Row (const UnwindPlan::Row& rhs) = default;
412
413         bool
414         operator == (const Row &rhs) const;
415
416         bool
417         GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
418     
419         void
420         SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location);
421
422         void
423         RemoveRegisterInfo (uint32_t reg_num);
424
425         lldb::addr_t
426         GetOffset() const
427         {
428             return m_offset;
429         }
430
431         void
432         SetOffset(lldb::addr_t offset)
433         {
434             m_offset = offset;
435         }
436
437         void
438         SlideOffset(lldb::addr_t offset)
439         {
440             m_offset += offset;
441         }
442
443         CFAValue& GetCFAValue()
444         {
445             return m_cfa_value;
446         }
447
448         bool
449         SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, 
450                                               int32_t offset, 
451                                               bool can_replace);
452
453         bool
454         SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, 
455                                               int32_t offset, 
456                                               bool can_replace);
457
458         bool
459         SetRegisterLocationToUndefined (uint32_t reg_num, 
460                                         bool can_replace, 
461                                         bool can_replace_only_if_unspecified);
462
463         bool
464         SetRegisterLocationToUnspecified (uint32_t reg_num, 
465                                           bool can_replace);
466
467         bool
468         SetRegisterLocationToRegister (uint32_t reg_num, 
469                                        uint32_t other_reg_num,
470                                        bool can_replace);
471
472         bool
473         SetRegisterLocationToSame (uint32_t reg_num, 
474                                    bool must_replace);
475
476         void
477         Clear ();
478
479         void
480         Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const;
481
482     protected:
483         typedef std::map<uint32_t, RegisterLocation> collection;
484         lldb::addr_t m_offset;      // Offset into the function for this row
485
486         CFAValue m_cfa_value;
487         collection m_register_locations;
488     }; // class Row
489
490 public:
491
492     typedef std::shared_ptr<Row> RowSP;
493
494     UnwindPlan (lldb::RegisterKind reg_kind) : 
495         m_row_list (), 
496         m_plan_valid_address_range (), 
497         m_register_kind (reg_kind), 
498         m_return_addr_register (LLDB_INVALID_REGNUM),
499         m_source_name (),
500         m_plan_is_sourced_from_compiler (eLazyBoolCalculate),
501         m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate),
502         m_lsda_address (),
503         m_personality_func_addr ()
504     {
505     }
506
507     // Performs a deep copy of the plan, including all the rows (expensive).
508     UnwindPlan (const UnwindPlan &rhs) :
509         m_plan_valid_address_range (rhs.m_plan_valid_address_range),
510         m_register_kind (rhs.m_register_kind),
511         m_return_addr_register (rhs.m_return_addr_register),
512         m_source_name (rhs.m_source_name),
513         m_plan_is_sourced_from_compiler (rhs.m_plan_is_sourced_from_compiler),
514         m_plan_is_valid_at_all_instruction_locations (rhs.m_plan_is_valid_at_all_instruction_locations),
515         m_lsda_address (rhs.m_lsda_address),
516         m_personality_func_addr (rhs.m_personality_func_addr)
517     {
518         m_row_list.reserve (rhs.m_row_list.size());
519         for (const RowSP &row_sp: rhs.m_row_list)
520             m_row_list.emplace_back (new Row (*row_sp));
521     }
522
523     ~UnwindPlan ()
524         {
525         }
526
527     void 
528     Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const;
529
530     void 
531     AppendRow (const RowSP& row_sp);
532
533     void
534     InsertRow (const RowSP& row_sp);
535
536     // Returns a pointer to the best row for the given offset into the function's instructions.
537     // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned.
538     // In practice, the UnwindPlan for a function with no known start address will be the architectural default
539     // UnwindPlan which will only have one row.
540     UnwindPlan::RowSP
541     GetRowForFunctionOffset (int offset) const;
542
543     lldb::RegisterKind
544     GetRegisterKind () const
545     {
546         return m_register_kind;
547     }
548
549     void
550     SetRegisterKind (lldb::RegisterKind kind)
551     {
552         m_register_kind = kind;
553     }
554     
555     void
556     SetReturnAddressRegister (uint32_t regnum)
557     {
558         m_return_addr_register = regnum;
559     }
560     
561     uint32_t
562     GetReturnAddressRegister (void)
563     {
564         return m_return_addr_register;
565     }
566
567     uint32_t
568     GetInitialCFARegister () const
569     {
570         if (m_row_list.empty())
571             return LLDB_INVALID_REGNUM;
572         return m_row_list.front()->GetCFAValue().GetRegisterNumber();
573     }
574
575     // This UnwindPlan may not be valid at every address of the function span.  
576     // For instance, a FastUnwindPlan will not be valid at the prologue setup 
577     // instructions - only in the body of the function.
578     void
579     SetPlanValidAddressRange (const AddressRange& range);
580
581     const AddressRange &
582     GetAddressRange () const
583     {
584         return m_plan_valid_address_range;
585     }
586
587     bool
588     PlanValidAtAddress (Address addr);
589
590     bool
591     IsValidRowIndex (uint32_t idx) const;
592
593     const UnwindPlan::RowSP
594     GetRowAtIndex (uint32_t idx) const;
595
596     const UnwindPlan::RowSP
597     GetLastRow () const;
598
599     lldb_private::ConstString
600     GetSourceName () const;
601
602     void
603     SetSourceName (const char *);
604
605     // Was this UnwindPlan emitted by a compiler?
606     lldb_private::LazyBool
607     GetSourcedFromCompiler () const
608     {
609         return m_plan_is_sourced_from_compiler;
610     }
611
612     // Was this UnwindPlan emitted by a compiler?
613     void
614     SetSourcedFromCompiler (lldb_private::LazyBool from_compiler)
615     {
616         m_plan_is_sourced_from_compiler = from_compiler;
617     }
618
619     // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
620     // e.g. for exception handling.
621     lldb_private::LazyBool
622     GetUnwindPlanValidAtAllInstructions () const
623     {
624         return m_plan_is_valid_at_all_instruction_locations;
625     }
626
627     // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
628     // e.g. for exception handling.
629     void
630     SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn)
631     {
632         m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
633     }
634
635     int
636     GetRowCount () const;
637
638     void
639     Clear()
640     {
641         m_row_list.clear();
642         m_plan_valid_address_range.Clear();
643         m_register_kind = lldb::eRegisterKindDWARF;
644         m_source_name.Clear();
645         m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
646         m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
647         m_lsda_address.Clear();
648         m_personality_func_addr.Clear();
649     }
650
651     const RegisterInfo *
652     GetRegisterInfo (Thread* thread, uint32_t reg_num) const;
653
654     Address
655     GetLSDAAddress () const
656     {
657         return m_lsda_address;
658     }
659
660     void
661     SetLSDAAddress (Address lsda_addr)
662     {
663         m_lsda_address = lsda_addr;
664     }
665
666     Address
667     GetPersonalityFunctionPtr () const
668     {
669         return m_personality_func_addr;
670     }
671
672     void
673     SetPersonalityFunctionPtr (Address presonality_func_ptr)
674     {
675         m_personality_func_addr = presonality_func_ptr;
676     }
677
678 private:
679
680     
681     typedef std::vector<RowSP> collection;
682     collection m_row_list;
683     AddressRange m_plan_valid_address_range;
684     lldb::RegisterKind m_register_kind;   // The RegisterKind these register numbers are in terms of - will need to be
685                                           // translated to lldb native reg nums at unwind time
686     uint32_t m_return_addr_register;      // The register that has the return address for the caller frame
687                                           // e.g. the lr on arm
688     lldb_private::ConstString m_source_name;  // for logging, where this UnwindPlan originated from
689     lldb_private::LazyBool m_plan_is_sourced_from_compiler;
690     lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
691
692     Address m_lsda_address;                 // Where the language specific data area exists in the module - used 
693                                             // in exception handling.
694     Address m_personality_func_addr;        // The address of a pointer to the personality function - used in
695                                             // exception handling.
696 }; // class UnwindPlan
697
698 } // namespace lldb_private
699
700 #endif //liblldb_UnwindPlan_h