UnwindPlan.h revision a092d901bec2beaed29603acad318d8d93da3f4a
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 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), m_cfa_reg_num(rhs.m_cfa_reg_num), m_cfa_offset(rhs.m_cfa_offset) 245 { 246 for (collection::const_iterator idx = rhs.m_register_locations.begin(); idx != rhs.m_register_locations.end(); ++idx) 247 { 248 m_register_locations[idx->first] = idx->second; 249 } 250 } 251 252 bool 253 operator == (const Row &rhs) const; 254 255 bool 256 GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const; 257 258 void 259 SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location); 260 261 lldb::addr_t 262 GetOffset() const 263 { 264 return m_offset; 265 } 266 267 void 268 SetOffset(lldb::addr_t offset) 269 { 270 m_offset = offset; 271 } 272 273 void 274 SlideOffset(lldb::addr_t offset) 275 { 276 m_offset += offset; 277 } 278 279 uint32_t 280 GetCFARegister () const 281 { 282 return m_cfa_reg_num; 283 } 284 285 bool 286 SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, 287 int32_t offset, 288 bool can_replace); 289 290 bool 291 SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, 292 int32_t offset, 293 bool can_replace); 294 295 bool 296 SetRegisterLocationToUndefined (uint32_t reg_num, 297 bool can_replace, 298 bool can_replace_only_if_unspecified); 299 300 bool 301 SetRegisterLocationToUnspecified (uint32_t reg_num, 302 bool can_replace); 303 304 bool 305 SetRegisterLocationToRegister (uint32_t reg_num, 306 uint32_t other_reg_num, 307 bool can_replace); 308 309 bool 310 SetRegisterLocationToSame (uint32_t reg_num, 311 bool must_replace); 312 313 314 315 void 316 SetCFARegister (uint32_t reg_num); 317 318 int32_t 319 GetCFAOffset () const 320 { 321 return m_cfa_offset; 322 } 323 324 void 325 SetCFAOffset (int32_t offset) 326 { 327 m_cfa_offset = offset; 328 } 329 330 // Return the number of registers we have locations for 331 int 332 GetRegisterCount () const 333 { 334 return m_register_locations.size(); 335 } 336 337 void 338 Clear (); 339 340 void 341 Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const; 342 343 protected: 344 typedef std::map<uint32_t, RegisterLocation> collection; 345 lldb::addr_t m_offset; // Offset into the function for this row 346 uint32_t m_cfa_reg_num; // The Call Frame Address register number 347 int32_t m_cfa_offset; // The offset from the CFA for this row 348 collection m_register_locations; 349 }; // class Row 350 351public: 352 353 typedef STD_SHARED_PTR(Row) RowSP; 354 355 UnwindPlan (lldb::RegisterKind reg_kind) : 356 m_row_list (), 357 m_plan_valid_address_range (), 358 m_register_kind (reg_kind), 359 m_source_name () 360 { 361 } 362 363 ~UnwindPlan () 364 { 365 } 366 367 void 368 Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const; 369 370 void 371 AppendRow (RowSP row); 372 373 // Returns a pointer to the best row for the given offset into the function's instructions. 374 // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned. 375 // In practice, the UnwindPlan for a function with no known start address will be the architectural default 376 // UnwindPlan which will only have one row. 377 UnwindPlan::RowSP 378 GetRowForFunctionOffset (int offset) const; 379 380 lldb::RegisterKind 381 GetRegisterKind () const 382 { 383 return m_register_kind; 384 } 385 386 void 387 SetRegisterKind (lldb::RegisterKind kind) 388 { 389 m_register_kind = kind; 390 } 391 392 uint32_t 393 GetInitialCFARegister () const 394 { 395 if (m_row_list.empty()) 396 return LLDB_INVALID_REGNUM; 397 return m_row_list.front()->GetCFARegister(); 398 } 399 400 // This UnwindPlan may not be valid at every address of the function span. 401 // For instance, a FastUnwindPlan will not be valid at the prologue setup 402 // instructions - only in the body of the function. 403 void 404 SetPlanValidAddressRange (const AddressRange& range); 405 406 const AddressRange & 407 GetAddressRange () const 408 { 409 return m_plan_valid_address_range; 410 } 411 412 bool 413 PlanValidAtAddress (Address addr); 414 415 bool 416 IsValidRowIndex (uint32_t idx) const; 417 418 const UnwindPlan::RowSP 419 GetRowAtIndex (uint32_t idx) const; 420 421 const UnwindPlan::RowSP 422 GetLastRow () const; 423 424 lldb_private::ConstString 425 GetSourceName () const; 426 427 void 428 SetSourceName (const char *); 429 430 int 431 GetRowCount () const; 432 433 void 434 Clear() 435 { 436 m_row_list.clear(); 437 m_plan_valid_address_range.Clear(); 438 m_register_kind = lldb::eRegisterKindDWARF; 439 m_source_name.Clear(); 440 } 441 442 const RegisterInfo * 443 GetRegisterInfo (Thread* thread, uint32_t reg_num) const; 444 445private: 446 447 448 typedef std::vector<RowSP> collection; 449 collection m_row_list; 450 AddressRange m_plan_valid_address_range; 451 lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers are in terms of - will need to be 452 // translated to lldb native reg nums at unwind time 453 lldb_private::ConstString m_source_name; // for logging, where this UnwindPlan originated from 454}; // class UnwindPlan 455 456} // namespace lldb_private 457 458#endif //liblldb_UnwindPlan_h 459