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