]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/lldb/Symbol/UnwindPlan.h
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / include / lldb / Symbol / UnwindPlan.h
1 //===-- UnwindPlan.h --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_UnwindPlan_h
11 #define liblldb_UnwindPlan_h
12
13 // C Includes
14 // C++ Includes
15 #include <map>
16 #include <memory>
17 #include <vector>
18
19 // Other libraries and framework includes
20 // Project includes
21 #include "lldb/lldb-private.h"
22 #include "lldb/Core/AddressRange.h"
23 #include "lldb/Core/Stream.h"
24 #include "lldb/Core/ConstString.h"
25
26 namespace lldb_private {
27
28 // The UnwindPlan object specifies how to unwind out of a function - where
29 // this function saves the caller's register values before modifying them
30 // (for non-volatile aka saved registers) and how to find this frame's
31 // Canonical Frame Address (CFA).
32
33 // Most commonly, registers are saved on the stack, offset some bytes from
34 // the Canonical Frame Address, or CFA, which is the starting address of
35 // this function's stack frame (the CFA is same as the eh_frame's CFA,
36 // whatever that may be on a given architecture).
37 // The CFA address for the stack frame does not change during
38 // the lifetime of the function.
39
40 // Internally, the UnwindPlan is structured as a vector of register locations
41 // organized by code address in the function, showing which registers have been
42 // saved at that point and where they are saved.  
43 // It can be thought of as the expanded table form of the DWARF CFI 
44 // encoded information.
45
46 // Other unwind information sources will be converted into UnwindPlans before
47 // being added to a FuncUnwinders object.  The unwind source may be 
48 // an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based 
49 // prologue analysis.
50 // The UnwindPlan is the canonical form of this information that the unwinder
51 // code will use when walking the stack.
52
53 class UnwindPlan {
54 public:
55     class Row {
56     public:
57         class RegisterLocation
58         {
59         public:
60             enum RestoreType
61                 {
62                     unspecified,        // not specified, we may be able to assume this 
63                                         // is the same register. gcc doesn't specify all 
64                                         // initial values so we really don't know...
65                     undefined,          // reg is not available, e.g. volatile reg
66                     same,               // reg is unchanged
67                     atCFAPlusOffset,    // reg = deref(CFA + offset)
68                     isCFAPlusOffset,    // reg = CFA + offset
69                     inOtherRegister,    // reg = other reg
70                     atDWARFExpression,  // reg = deref(eval(dwarf_expr))
71                     isDWARFExpression   // reg = eval(dwarf_expr)
72                 };
73
74             RegisterLocation() : 
75                 m_type(unspecified), 
76                 m_location() 
77             {
78             }
79
80             bool
81             operator == (const RegisterLocation& rhs) const;
82     
83             bool
84             operator != (const RegisterLocation &rhs) const
85             {
86                 return !(*this == rhs);
87             }
88             
89             void 
90             SetUnspecified()
91             {
92                 m_type = unspecified;
93             }
94
95             void 
96             SetUndefined()
97             {
98                 m_type = undefined;
99             }
100     
101             void 
102             SetSame()
103             {
104                 m_type = same;
105             }
106     
107             bool 
108             IsSame () const 
109             { 
110                 return m_type == same; 
111             }
112
113             bool 
114             IsUnspecified () const
115             {
116                 return m_type == unspecified; 
117             }
118
119             bool
120             IsUndefined () const
121             {
122                 return m_type == undefined;
123             }
124
125             bool 
126             IsCFAPlusOffset () const
127             {
128                 return m_type == isCFAPlusOffset; 
129             }
130
131             bool 
132             IsAtCFAPlusOffset () const
133             {
134                 return m_type == atCFAPlusOffset; 
135             }
136
137             bool
138             IsInOtherRegister () const
139             {
140                 return m_type == inOtherRegister; 
141             }
142
143             bool
144             IsAtDWARFExpression () const
145             {
146                 return m_type == atDWARFExpression; 
147             }
148
149             bool
150             IsDWARFExpression () const
151             { 
152                 return m_type == isDWARFExpression; 
153             }
154
155             void
156             SetAtCFAPlusOffset (int32_t offset)
157             {
158                 m_type = atCFAPlusOffset;
159                 m_location.offset = offset;
160             }
161     
162             void
163             SetIsCFAPlusOffset (int32_t offset)
164             {
165                 m_type = isCFAPlusOffset;
166                 m_location.offset = offset;
167             }
168     
169             void 
170             SetInRegister (uint32_t reg_num)
171             {
172                 m_type = inOtherRegister;
173                 m_location.reg_num = reg_num;
174             }
175     
176             uint32_t
177             GetRegisterNumber () const
178             {
179                 if (m_type == inOtherRegister)
180                     return m_location.reg_num; 
181                 return LLDB_INVALID_REGNUM;
182             }
183
184             RestoreType
185             GetLocationType () const
186             {
187                 return m_type; 
188             }
189
190             int32_t
191             GetOffset () const
192             {
193                 if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
194                     return m_location.offset;
195                 return 0;
196             }
197             
198             void
199             GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const
200             {
201                 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
202                 {
203                     *opcodes = m_location.expr.opcodes; 
204                     len = m_location.expr.length; 
205                 }
206                 else
207                 {
208                     *opcodes = nullptr;
209                     len = 0;
210                 }
211             }
212
213             void
214             SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len);
215     
216             void
217             SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
218
219             const uint8_t *
220             GetDWARFExpressionBytes () 
221             {
222                 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
223                     return m_location.expr.opcodes; 
224                 return nullptr;
225             }
226
227             int
228             GetDWARFExpressionLength ()
229             {
230                 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
231                     return m_location.expr.length; 
232                 return 0;
233             }
234
235             void
236             Dump (Stream &s, 
237                   const UnwindPlan* unwind_plan, 
238                   const UnwindPlan::Row* row, 
239                   Thread* thread, 
240                   bool verbose) const;
241
242         private:
243             RestoreType m_type;            // How do we locate this register?
244             union
245             {
246                 // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
247                 int32_t offset;
248                 // For m_type == inOtherRegister
249                 uint32_t reg_num; // The register number
250                 // For m_type == atDWARFExpression or m_type == isDWARFExpression
251                 struct {
252                     const uint8_t *opcodes;
253                     uint16_t length;
254                 } expr;
255             } m_location;
256         };
257     
258         class CFAValue
259         {
260         public:
261             enum ValueType
262             {
263                 unspecified,                  // not specified
264                 isRegisterPlusOffset,         // CFA = register + offset
265                 isRegisterDereferenced,       // CFA = [reg]
266                 isDWARFExpression             // CFA = eval(dwarf_expr)
267             };
268
269             CFAValue() :
270                 m_type(unspecified),
271                 m_value()
272             {
273             }
274
275             bool
276             operator == (const CFAValue& rhs) const;
277
278             bool
279             operator != (const CFAValue &rhs) const
280             {
281                 return !(*this == rhs);
282             }
283
284             void
285             SetUnspecified()
286             {
287                 m_type = unspecified;
288             }
289
290             bool
291             IsUnspecified () const
292             {
293                 return m_type == unspecified;
294             }
295
296             bool
297             IsRegisterPlusOffset () const
298             {
299                 return m_type == isRegisterPlusOffset;
300             }
301
302             void
303             SetIsRegisterPlusOffset (uint32_t reg_num, int32_t offset)
304             {
305                 m_type = isRegisterPlusOffset;
306                 m_value.reg.reg_num = reg_num;
307                 m_value.reg.offset = offset;
308             }
309
310             bool
311             IsRegisterDereferenced () const
312             {
313                 return m_type == isRegisterDereferenced;
314             }
315
316             void
317             SetIsRegisterDereferenced (uint32_t reg_num)
318             {
319                 m_type = isRegisterDereferenced;
320                 m_value.reg.reg_num = reg_num;
321             }
322
323             bool
324             IsDWARFExpression () const
325             {
326                 return m_type == isDWARFExpression;
327             }
328
329             void
330             SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
331             {
332                 m_type = isDWARFExpression;
333                 m_value.expr.opcodes = opcodes;
334                 m_value.expr.length = len;
335             }
336
337             uint32_t
338             GetRegisterNumber () const
339             {
340                 if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset)
341                     return m_value.reg.reg_num;
342                 return LLDB_INVALID_REGNUM;
343             }
344
345             ValueType
346             GetValueType () const
347             {
348                 return m_type;
349             }
350
351             int32_t
352             GetOffset () const
353             {
354                 if (m_type == isRegisterPlusOffset)
355                     return m_value.reg.offset;
356                 return 0;
357             }
358
359             void IncOffset (int32_t delta)
360             {
361                 if (m_type == isRegisterPlusOffset)
362                     m_value.reg.offset += delta;
363             }
364
365             void SetOffset (int32_t offset)
366             {
367                 if (m_type == isRegisterPlusOffset)
368                     m_value.reg.offset = offset;
369             }
370
371             void
372             GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const
373             {
374                 if (m_type == isDWARFExpression)
375                 {
376                     *opcodes = m_value.expr.opcodes;
377                     len = m_value.expr.length;
378                 }
379                 else
380                 {
381                     *opcodes = nullptr;
382                     len = 0;
383                 }
384             }
385
386             const uint8_t *
387             GetDWARFExpressionBytes ()
388             {
389                 if (m_type == isDWARFExpression)
390                     return m_value.expr.opcodes;
391                 return nullptr;
392             }
393
394             int
395             GetDWARFExpressionLength ()
396             {
397                 if (m_type == isDWARFExpression)
398                     return m_value.expr.length;
399                 return 0;
400             }
401
402             void
403             Dump (Stream &s,
404                   const UnwindPlan* unwind_plan,
405                   Thread* thread) const;
406
407         private:
408             ValueType m_type;            // How do we compute CFA value?
409             union
410             {
411                 struct {
412                     // For m_type == isRegisterPlusOffset or m_type == isRegisterDereferenced
413                     uint32_t reg_num; // The register number
414                     // For m_type == isRegisterPlusOffset
415                     int32_t offset;
416                 } reg;
417                 // For m_type == isDWARFExpression
418                 struct {
419                     const uint8_t *opcodes;
420                     uint16_t length;
421                 } expr;
422             } m_value;
423         }; // class CFAValue
424
425     public:
426         Row ();
427
428         Row (const UnwindPlan::Row& rhs) = default;
429
430         bool
431         operator == (const Row &rhs) const;
432
433         bool
434         GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
435     
436         void
437         SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location);
438
439         void
440         RemoveRegisterInfo (uint32_t reg_num);
441
442         lldb::addr_t
443         GetOffset() const
444         {
445             return m_offset;
446         }
447
448         void
449         SetOffset(lldb::addr_t offset)
450         {
451             m_offset = offset;
452         }
453
454         void
455         SlideOffset(lldb::addr_t offset)
456         {
457             m_offset += offset;
458         }
459
460         CFAValue& GetCFAValue()
461         {
462             return m_cfa_value;
463         }
464
465         bool
466         SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, 
467                                               int32_t offset, 
468                                               bool can_replace);
469
470         bool
471         SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, 
472                                               int32_t offset, 
473                                               bool can_replace);
474
475         bool
476         SetRegisterLocationToUndefined (uint32_t reg_num, 
477                                         bool can_replace, 
478                                         bool can_replace_only_if_unspecified);
479
480         bool
481         SetRegisterLocationToUnspecified (uint32_t reg_num, 
482                                           bool can_replace);
483
484         bool
485         SetRegisterLocationToRegister (uint32_t reg_num, 
486                                        uint32_t other_reg_num,
487                                        bool can_replace);
488
489         bool
490         SetRegisterLocationToSame (uint32_t reg_num, 
491                                    bool must_replace);
492
493         void
494         Clear ();
495
496         void
497         Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const;
498
499     protected:
500         typedef std::map<uint32_t, RegisterLocation> collection;
501         lldb::addr_t m_offset;      // Offset into the function for this row
502
503         CFAValue m_cfa_value;
504         collection m_register_locations;
505     }; // class Row
506
507 public:
508     typedef std::shared_ptr<Row> RowSP;
509
510     UnwindPlan (lldb::RegisterKind reg_kind) : 
511         m_row_list (), 
512         m_plan_valid_address_range (), 
513         m_register_kind (reg_kind), 
514         m_return_addr_register (LLDB_INVALID_REGNUM),
515         m_source_name (),
516         m_plan_is_sourced_from_compiler (eLazyBoolCalculate),
517         m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate),
518         m_lsda_address (),
519         m_personality_func_addr ()
520     {
521     }
522
523     // Performs a deep copy of the plan, including all the rows (expensive).
524     UnwindPlan (const UnwindPlan &rhs) :
525         m_plan_valid_address_range (rhs.m_plan_valid_address_range),
526         m_register_kind (rhs.m_register_kind),
527         m_return_addr_register (rhs.m_return_addr_register),
528         m_source_name (rhs.m_source_name),
529         m_plan_is_sourced_from_compiler (rhs.m_plan_is_sourced_from_compiler),
530         m_plan_is_valid_at_all_instruction_locations (rhs.m_plan_is_valid_at_all_instruction_locations),
531         m_lsda_address (rhs.m_lsda_address),
532         m_personality_func_addr (rhs.m_personality_func_addr)
533     {
534         m_row_list.reserve (rhs.m_row_list.size());
535         for (const RowSP &row_sp: rhs.m_row_list)
536             m_row_list.emplace_back (new Row (*row_sp));
537     }
538
539     ~UnwindPlan() = default;
540
541     void 
542     Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const;
543
544     void 
545     AppendRow (const RowSP& row_sp);
546
547     void
548     InsertRow (const RowSP& row_sp, bool replace_existing = false);
549
550     // Returns a pointer to the best row for the given offset into the function's instructions.
551     // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned.
552     // In practice, the UnwindPlan for a function with no known start address will be the architectural default
553     // UnwindPlan which will only have one row.
554     UnwindPlan::RowSP
555     GetRowForFunctionOffset (int offset) const;
556
557     lldb::RegisterKind
558     GetRegisterKind () const
559     {
560         return m_register_kind;
561     }
562
563     void
564     SetRegisterKind (lldb::RegisterKind kind)
565     {
566         m_register_kind = kind;
567     }
568     
569     void
570     SetReturnAddressRegister (uint32_t regnum)
571     {
572         m_return_addr_register = regnum;
573     }
574     
575     uint32_t
576     GetReturnAddressRegister (void)
577     {
578         return m_return_addr_register;
579     }
580
581     uint32_t
582     GetInitialCFARegister () const
583     {
584         if (m_row_list.empty())
585             return LLDB_INVALID_REGNUM;
586         return m_row_list.front()->GetCFAValue().GetRegisterNumber();
587     }
588
589     // This UnwindPlan may not be valid at every address of the function span.  
590     // For instance, a FastUnwindPlan will not be valid at the prologue setup 
591     // instructions - only in the body of the function.
592     void
593     SetPlanValidAddressRange (const AddressRange& range);
594
595     const AddressRange &
596     GetAddressRange () const
597     {
598         return m_plan_valid_address_range;
599     }
600
601     bool
602     PlanValidAtAddress (Address addr);
603
604     bool
605     IsValidRowIndex (uint32_t idx) const;
606
607     const UnwindPlan::RowSP
608     GetRowAtIndex (uint32_t idx) const;
609
610     const UnwindPlan::RowSP
611     GetLastRow () const;
612
613     lldb_private::ConstString
614     GetSourceName () const;
615
616     void
617     SetSourceName (const char *);
618
619     // Was this UnwindPlan emitted by a compiler?
620     lldb_private::LazyBool
621     GetSourcedFromCompiler () const
622     {
623         return m_plan_is_sourced_from_compiler;
624     }
625
626     // Was this UnwindPlan emitted by a compiler?
627     void
628     SetSourcedFromCompiler (lldb_private::LazyBool from_compiler)
629     {
630         m_plan_is_sourced_from_compiler = from_compiler;
631     }
632
633     // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
634     // e.g. for exception handling.
635     lldb_private::LazyBool
636     GetUnwindPlanValidAtAllInstructions () const
637     {
638         return m_plan_is_valid_at_all_instruction_locations;
639     }
640
641     // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
642     // e.g. for exception handling.
643     void
644     SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn)
645     {
646         m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
647     }
648
649     int
650     GetRowCount () const;
651
652     void
653     Clear()
654     {
655         m_row_list.clear();
656         m_plan_valid_address_range.Clear();
657         m_register_kind = lldb::eRegisterKindDWARF;
658         m_source_name.Clear();
659         m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
660         m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
661         m_lsda_address.Clear();
662         m_personality_func_addr.Clear();
663     }
664
665     const RegisterInfo *
666     GetRegisterInfo (Thread* thread, uint32_t reg_num) const;
667
668     Address
669     GetLSDAAddress () const
670     {
671         return m_lsda_address;
672     }
673
674     void
675     SetLSDAAddress (Address lsda_addr)
676     {
677         m_lsda_address = lsda_addr;
678     }
679
680     Address
681     GetPersonalityFunctionPtr () const
682     {
683         return m_personality_func_addr;
684     }
685
686     void
687     SetPersonalityFunctionPtr (Address presonality_func_ptr)
688     {
689         m_personality_func_addr = presonality_func_ptr;
690     }
691
692 private:
693     typedef std::vector<RowSP> collection;
694     collection m_row_list;
695     AddressRange m_plan_valid_address_range;
696     lldb::RegisterKind m_register_kind;   // The RegisterKind these register numbers are in terms of - will need to be
697                                           // translated to lldb native reg nums at unwind time
698     uint32_t m_return_addr_register;      // The register that has the return address for the caller frame
699                                           // e.g. the lr on arm
700     lldb_private::ConstString m_source_name;  // for logging, where this UnwindPlan originated from
701     lldb_private::LazyBool m_plan_is_sourced_from_compiler;
702     lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
703
704     Address m_lsda_address;                 // Where the language specific data area exists in the module - used 
705                                             // in exception handling.
706     Address m_personality_func_addr;        // The address of a pointer to the personality function - used in
707                                             // exception handling.
708 }; // class UnwindPlan
709
710 } // namespace lldb_private
711
712 #endif // liblldb_UnwindPlan_h