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