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