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