1296417Sdim//===-- UnwindPlan.h --------------------------------------------*- C++ -*-===// 2296417Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6296417Sdim// 7296417Sdim//===----------------------------------------------------------------------===// 8296417Sdim 9254721Semaste#ifndef liblldb_UnwindPlan_h 10254721Semaste#define liblldb_UnwindPlan_h 11254721Semaste 12296417Sdim#include <map> 13296417Sdim#include <memory> 14296417Sdim#include <vector> 15296417Sdim 16254721Semaste#include "lldb/Core/AddressRange.h" 17321369Sdim#include "lldb/Utility/ConstString.h" 18321369Sdim#include "lldb/Utility/Stream.h" 19314564Sdim#include "lldb/lldb-private.h" 20254721Semaste 21254721Semastenamespace lldb_private { 22254721Semaste 23341825Sdim// The UnwindPlan object specifies how to unwind out of a function - where this 24341825Sdim// function saves the caller's register values before modifying them (for non- 25341825Sdim// volatile aka saved registers) and how to find this frame's Canonical Frame 26344779Sdim// Address (CFA) or Aligned Frame Address (AFA). 27254721Semaste 28344779Sdim// CFA is a DWARF's Canonical Frame Address. 29341825Sdim// Most commonly, registers are saved on the stack, offset some bytes from the 30341825Sdim// Canonical Frame Address, or CFA, which is the starting address of this 31341825Sdim// function's stack frame (the CFA is same as the eh_frame's CFA, whatever that 32341825Sdim// may be on a given architecture). The CFA address for the stack frame does 33341825Sdim// not change during the lifetime of the function. 34254721Semaste 35344779Sdim// AFA is an artificially introduced Aligned Frame Address. 36344779Sdim// It is used only for stack frames with realignment (e.g. when some of the 37344779Sdim// locals has an alignment requirement higher than the stack alignment right 38344779Sdim// after the function call). It is used to access register values saved on the 39344779Sdim// stack after the realignment (and so they are inaccessible through the CFA). 40344779Sdim// AFA usually equals the stack pointer value right after the realignment. 41344779Sdim 42254721Semaste// Internally, the UnwindPlan is structured as a vector of register locations 43254721Semaste// organized by code address in the function, showing which registers have been 44341825Sdim// saved at that point and where they are saved. It can be thought of as the 45341825Sdim// expanded table form of the DWARF CFI encoded information. 46254721Semaste 47254721Semaste// Other unwind information sources will be converted into UnwindPlans before 48341825Sdim// being added to a FuncUnwinders object. The unwind source may be an eh_frame 49341825Sdim// FDE, a DWARF debug_frame FDE, or assembly language based prologue analysis. 50254721Semaste// The UnwindPlan is the canonical form of this information that the unwinder 51254721Semaste// code will use when walking the stack. 52254721Semaste 53254721Semasteclass UnwindPlan { 54254721Semastepublic: 55314564Sdim class Row { 56314564Sdim public: 57314564Sdim class RegisterLocation { 58254721Semaste public: 59314564Sdim enum RestoreType { 60314564Sdim unspecified, // not specified, we may be able to assume this 61314564Sdim // is the same register. gcc doesn't specify all 62314564Sdim // initial values so we really don't know... 63314564Sdim undefined, // reg is not available, e.g. volatile reg 64314564Sdim same, // reg is unchanged 65314564Sdim atCFAPlusOffset, // reg = deref(CFA + offset) 66314564Sdim isCFAPlusOffset, // reg = CFA + offset 67344779Sdim atAFAPlusOffset, // reg = deref(AFA + offset) 68344779Sdim isAFAPlusOffset, // reg = AFA + offset 69314564Sdim inOtherRegister, // reg = other reg 70314564Sdim atDWARFExpression, // reg = deref(eval(dwarf_expr)) 71314564Sdim isDWARFExpression // reg = eval(dwarf_expr) 72314564Sdim }; 73280031Sdim 74314564Sdim RegisterLocation() : m_type(unspecified), m_location() {} 75280031Sdim 76314564Sdim bool operator==(const RegisterLocation &rhs) const; 77254721Semaste 78314564Sdim bool operator!=(const RegisterLocation &rhs) const { 79314564Sdim return !(*this == rhs); 80314564Sdim } 81254721Semaste 82314564Sdim void SetUnspecified() { m_type = unspecified; } 83254721Semaste 84314564Sdim void SetUndefined() { m_type = undefined; } 85309124Sdim 86314564Sdim void SetSame() { m_type = same; } 87254721Semaste 88314564Sdim bool IsSame() const { return m_type == same; } 89254721Semaste 90314564Sdim bool IsUnspecified() const { return m_type == unspecified; } 91254721Semaste 92314564Sdim bool IsUndefined() const { return m_type == undefined; } 93254721Semaste 94314564Sdim bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; } 95254721Semaste 96314564Sdim bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; } 97254721Semaste 98344779Sdim bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; } 99344779Sdim 100344779Sdim bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; } 101344779Sdim 102314564Sdim bool IsInOtherRegister() const { return m_type == inOtherRegister; } 103254721Semaste 104314564Sdim bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; } 105254721Semaste 106314564Sdim bool IsDWARFExpression() const { return m_type == isDWARFExpression; } 107254721Semaste 108314564Sdim void SetAtCFAPlusOffset(int32_t offset) { 109314564Sdim m_type = atCFAPlusOffset; 110314564Sdim m_location.offset = offset; 111314564Sdim } 112254721Semaste 113314564Sdim void SetIsCFAPlusOffset(int32_t offset) { 114314564Sdim m_type = isCFAPlusOffset; 115314564Sdim m_location.offset = offset; 116314564Sdim } 117254721Semaste 118344779Sdim void SetAtAFAPlusOffset(int32_t offset) { 119344779Sdim m_type = atAFAPlusOffset; 120344779Sdim m_location.offset = offset; 121344779Sdim } 122344779Sdim 123344779Sdim void SetIsAFAPlusOffset(int32_t offset) { 124344779Sdim m_type = isAFAPlusOffset; 125344779Sdim m_location.offset = offset; 126344779Sdim } 127344779Sdim 128314564Sdim void SetInRegister(uint32_t reg_num) { 129314564Sdim m_type = inOtherRegister; 130314564Sdim m_location.reg_num = reg_num; 131314564Sdim } 132254721Semaste 133314564Sdim uint32_t GetRegisterNumber() const { 134314564Sdim if (m_type == inOtherRegister) 135314564Sdim return m_location.reg_num; 136314564Sdim return LLDB_INVALID_REGNUM; 137314564Sdim } 138288943Sdim 139314564Sdim RestoreType GetLocationType() const { return m_type; } 140288943Sdim 141314564Sdim int32_t GetOffset() const { 142344779Sdim switch(m_type) 143344779Sdim { 144344779Sdim case atCFAPlusOffset: 145344779Sdim case isCFAPlusOffset: 146344779Sdim case atAFAPlusOffset: 147344779Sdim case isAFAPlusOffset: 148314564Sdim return m_location.offset; 149344779Sdim default: 150344779Sdim return 0; 151344779Sdim } 152314564Sdim } 153288943Sdim 154314564Sdim void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const { 155314564Sdim if (m_type == atDWARFExpression || m_type == isDWARFExpression) { 156314564Sdim *opcodes = m_location.expr.opcodes; 157314564Sdim len = m_location.expr.length; 158314564Sdim } else { 159314564Sdim *opcodes = nullptr; 160314564Sdim len = 0; 161314564Sdim } 162314564Sdim } 163288943Sdim 164314564Sdim void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len); 165288943Sdim 166314564Sdim void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len); 167288943Sdim 168314564Sdim const uint8_t *GetDWARFExpressionBytes() { 169314564Sdim if (m_type == atDWARFExpression || m_type == isDWARFExpression) 170314564Sdim return m_location.expr.opcodes; 171314564Sdim return nullptr; 172314564Sdim } 173288943Sdim 174314564Sdim int GetDWARFExpressionLength() { 175314564Sdim if (m_type == atDWARFExpression || m_type == isDWARFExpression) 176314564Sdim return m_location.expr.length; 177314564Sdim return 0; 178314564Sdim } 179288943Sdim 180314564Sdim void Dump(Stream &s, const UnwindPlan *unwind_plan, 181314564Sdim const UnwindPlan::Row *row, Thread *thread, bool verbose) const; 182288943Sdim 183314564Sdim private: 184314564Sdim RestoreType m_type; // How do we locate this register? 185314564Sdim union { 186314564Sdim // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset 187314564Sdim int32_t offset; 188314564Sdim // For m_type == inOtherRegister 189314564Sdim uint32_t reg_num; // The register number 190314564Sdim // For m_type == atDWARFExpression or m_type == isDWARFExpression 191314564Sdim struct { 192314564Sdim const uint8_t *opcodes; 193314564Sdim uint16_t length; 194314564Sdim } expr; 195314564Sdim } m_location; 196314564Sdim }; 197288943Sdim 198344779Sdim class FAValue { 199314564Sdim public: 200314564Sdim enum ValueType { 201314564Sdim unspecified, // not specified 202344779Sdim isRegisterPlusOffset, // FA = register + offset 203344779Sdim isRegisterDereferenced, // FA = [reg] 204360784Sdim isDWARFExpression, // FA = eval(dwarf_expr) 205360784Sdim isRaSearch, // FA = SP + offset + ??? 206314564Sdim }; 207288943Sdim 208344779Sdim FAValue() : m_type(unspecified), m_value() {} 209288943Sdim 210344779Sdim bool operator==(const FAValue &rhs) const; 211288943Sdim 212344779Sdim bool operator!=(const FAValue &rhs) const { return !(*this == rhs); } 213288943Sdim 214314564Sdim void SetUnspecified() { m_type = unspecified; } 215288943Sdim 216314564Sdim bool IsUnspecified() const { return m_type == unspecified; } 217288943Sdim 218360784Sdim void SetRaSearch(int32_t offset) { 219360784Sdim m_type = isRaSearch; 220360784Sdim m_value.ra_search_offset = offset; 221360784Sdim } 222360784Sdim 223314564Sdim bool IsRegisterPlusOffset() const { 224314564Sdim return m_type == isRegisterPlusOffset; 225314564Sdim } 226288943Sdim 227314564Sdim void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) { 228314564Sdim m_type = isRegisterPlusOffset; 229314564Sdim m_value.reg.reg_num = reg_num; 230314564Sdim m_value.reg.offset = offset; 231314564Sdim } 232288943Sdim 233314564Sdim bool IsRegisterDereferenced() const { 234314564Sdim return m_type == isRegisterDereferenced; 235314564Sdim } 236288943Sdim 237314564Sdim void SetIsRegisterDereferenced(uint32_t reg_num) { 238314564Sdim m_type = isRegisterDereferenced; 239314564Sdim m_value.reg.reg_num = reg_num; 240314564Sdim } 241288943Sdim 242314564Sdim bool IsDWARFExpression() const { return m_type == isDWARFExpression; } 243288943Sdim 244314564Sdim void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) { 245314564Sdim m_type = isDWARFExpression; 246314564Sdim m_value.expr.opcodes = opcodes; 247314564Sdim m_value.expr.length = len; 248314564Sdim } 249288943Sdim 250314564Sdim uint32_t GetRegisterNumber() const { 251314564Sdim if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset) 252314564Sdim return m_value.reg.reg_num; 253314564Sdim return LLDB_INVALID_REGNUM; 254314564Sdim } 255254721Semaste 256314564Sdim ValueType GetValueType() const { return m_type; } 257288943Sdim 258314564Sdim int32_t GetOffset() const { 259360784Sdim switch (m_type) { 260360784Sdim case isRegisterPlusOffset: 261360784Sdim return m_value.reg.offset; 262360784Sdim case isRaSearch: 263360784Sdim return m_value.ra_search_offset; 264360784Sdim default: 265360784Sdim return 0; 266360784Sdim } 267314564Sdim } 268254721Semaste 269314564Sdim void IncOffset(int32_t delta) { 270314564Sdim if (m_type == isRegisterPlusOffset) 271314564Sdim m_value.reg.offset += delta; 272314564Sdim } 273280031Sdim 274314564Sdim void SetOffset(int32_t offset) { 275314564Sdim if (m_type == isRegisterPlusOffset) 276314564Sdim m_value.reg.offset = offset; 277314564Sdim } 278280031Sdim 279314564Sdim void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const { 280314564Sdim if (m_type == isDWARFExpression) { 281314564Sdim *opcodes = m_value.expr.opcodes; 282314564Sdim len = m_value.expr.length; 283314564Sdim } else { 284314564Sdim *opcodes = nullptr; 285314564Sdim len = 0; 286254721Semaste } 287314564Sdim } 288254721Semaste 289314564Sdim const uint8_t *GetDWARFExpressionBytes() { 290314564Sdim if (m_type == isDWARFExpression) 291314564Sdim return m_value.expr.opcodes; 292314564Sdim return nullptr; 293314564Sdim } 294254721Semaste 295314564Sdim int GetDWARFExpressionLength() { 296314564Sdim if (m_type == isDWARFExpression) 297314564Sdim return m_value.expr.length; 298314564Sdim return 0; 299314564Sdim } 300254721Semaste 301314564Sdim void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const; 302280031Sdim 303314564Sdim private: 304314564Sdim ValueType m_type; // How do we compute CFA value? 305314564Sdim union { 306314564Sdim struct { 307314564Sdim // For m_type == isRegisterPlusOffset or m_type == 308314564Sdim // isRegisterDereferenced 309314564Sdim uint32_t reg_num; // The register number 310314564Sdim // For m_type == isRegisterPlusOffset 311314564Sdim int32_t offset; 312314564Sdim } reg; 313314564Sdim // For m_type == isDWARFExpression 314314564Sdim struct { 315314564Sdim const uint8_t *opcodes; 316314564Sdim uint16_t length; 317314564Sdim } expr; 318360784Sdim // For m_type == isRaSearch 319360784Sdim int32_t ra_search_offset; 320314564Sdim } m_value; 321344779Sdim }; // class FAValue 322314564Sdim 323314564Sdim public: 324314564Sdim Row(); 325314564Sdim 326314564Sdim Row(const UnwindPlan::Row &rhs) = default; 327314564Sdim 328314564Sdim bool operator==(const Row &rhs) const; 329314564Sdim 330314564Sdim bool GetRegisterInfo(uint32_t reg_num, 331314564Sdim RegisterLocation ®ister_location) const; 332314564Sdim 333314564Sdim void SetRegisterInfo(uint32_t reg_num, 334314564Sdim const RegisterLocation register_location); 335314564Sdim 336314564Sdim void RemoveRegisterInfo(uint32_t reg_num); 337314564Sdim 338314564Sdim lldb::addr_t GetOffset() const { return m_offset; } 339314564Sdim 340314564Sdim void SetOffset(lldb::addr_t offset) { m_offset = offset; } 341314564Sdim 342314564Sdim void SlideOffset(lldb::addr_t offset) { m_offset += offset; } 343314564Sdim 344344779Sdim FAValue &GetCFAValue() { return m_cfa_value; } 345314564Sdim 346344779Sdim FAValue &GetAFAValue() { return m_afa_value; } 347344779Sdim 348314564Sdim bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, 349254721Semaste bool can_replace); 350254721Semaste 351314564Sdim bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, 352254721Semaste bool can_replace); 353254721Semaste 354314564Sdim bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, 355254721Semaste bool can_replace_only_if_unspecified); 356254721Semaste 357314564Sdim bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace); 358254721Semaste 359314564Sdim bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, 360254721Semaste bool can_replace); 361254721Semaste 362314564Sdim bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace); 363254721Semaste 364314564Sdim void Clear(); 365254721Semaste 366314564Sdim void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, 367314564Sdim lldb::addr_t base_addr) const; 368254721Semaste 369314564Sdim protected: 370314564Sdim typedef std::map<uint32_t, RegisterLocation> collection; 371314564Sdim lldb::addr_t m_offset; // Offset into the function for this row 372280031Sdim 373344779Sdim FAValue m_cfa_value; 374344779Sdim FAValue m_afa_value; 375314564Sdim collection m_register_locations; 376314564Sdim }; // class Row 377254721Semaste 378254721Semastepublic: 379314564Sdim typedef std::shared_ptr<Row> RowSP; 380254721Semaste 381314564Sdim UnwindPlan(lldb::RegisterKind reg_kind) 382314564Sdim : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind), 383314564Sdim m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(), 384314564Sdim m_plan_is_sourced_from_compiler(eLazyBoolCalculate), 385314564Sdim m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate), 386360784Sdim m_plan_is_for_signal_trap(eLazyBoolCalculate), 387314564Sdim m_lsda_address(), m_personality_func_addr() {} 388254721Semaste 389314564Sdim // Performs a deep copy of the plan, including all the rows (expensive). 390314564Sdim UnwindPlan(const UnwindPlan &rhs) 391314564Sdim : m_plan_valid_address_range(rhs.m_plan_valid_address_range), 392314564Sdim m_register_kind(rhs.m_register_kind), 393314564Sdim m_return_addr_register(rhs.m_return_addr_register), 394314564Sdim m_source_name(rhs.m_source_name), 395314564Sdim m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler), 396314564Sdim m_plan_is_valid_at_all_instruction_locations( 397314564Sdim rhs.m_plan_is_valid_at_all_instruction_locations), 398314564Sdim m_lsda_address(rhs.m_lsda_address), 399314564Sdim m_personality_func_addr(rhs.m_personality_func_addr) { 400314564Sdim m_row_list.reserve(rhs.m_row_list.size()); 401314564Sdim for (const RowSP &row_sp : rhs.m_row_list) 402314564Sdim m_row_list.emplace_back(new Row(*row_sp)); 403314564Sdim } 404288943Sdim 405314564Sdim ~UnwindPlan() = default; 406254721Semaste 407314564Sdim void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const; 408254721Semaste 409314564Sdim void AppendRow(const RowSP &row_sp); 410254721Semaste 411314564Sdim void InsertRow(const RowSP &row_sp, bool replace_existing = false); 412276479Sdim 413314564Sdim // Returns a pointer to the best row for the given offset into the function's 414341825Sdim // instructions. If offset is -1 it indicates that the function start is 415341825Sdim // unknown - the final row in the UnwindPlan is returned. In practice, the 416341825Sdim // UnwindPlan for a function with no known start address will be the 417341825Sdim // architectural default UnwindPlan which will only have one row. 418314564Sdim UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const; 419254721Semaste 420314564Sdim lldb::RegisterKind GetRegisterKind() const { return m_register_kind; } 421254721Semaste 422314564Sdim void SetRegisterKind(lldb::RegisterKind kind) { m_register_kind = kind; } 423254721Semaste 424314564Sdim void SetReturnAddressRegister(uint32_t regnum) { 425314564Sdim m_return_addr_register = regnum; 426314564Sdim } 427254721Semaste 428314564Sdim uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; } 429254721Semaste 430314564Sdim uint32_t GetInitialCFARegister() const { 431314564Sdim if (m_row_list.empty()) 432314564Sdim return LLDB_INVALID_REGNUM; 433314564Sdim return m_row_list.front()->GetCFAValue().GetRegisterNumber(); 434314564Sdim } 435254721Semaste 436314564Sdim // This UnwindPlan may not be valid at every address of the function span. 437314564Sdim // For instance, a FastUnwindPlan will not be valid at the prologue setup 438314564Sdim // instructions - only in the body of the function. 439314564Sdim void SetPlanValidAddressRange(const AddressRange &range); 440254721Semaste 441314564Sdim const AddressRange &GetAddressRange() const { 442314564Sdim return m_plan_valid_address_range; 443314564Sdim } 444254721Semaste 445314564Sdim bool PlanValidAtAddress(Address addr); 446254721Semaste 447314564Sdim bool IsValidRowIndex(uint32_t idx) const; 448254721Semaste 449314564Sdim const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const; 450254721Semaste 451314564Sdim const UnwindPlan::RowSP GetLastRow() const; 452254721Semaste 453314564Sdim lldb_private::ConstString GetSourceName() const; 454254721Semaste 455314564Sdim void SetSourceName(const char *); 456254721Semaste 457314564Sdim // Was this UnwindPlan emitted by a compiler? 458314564Sdim lldb_private::LazyBool GetSourcedFromCompiler() const { 459314564Sdim return m_plan_is_sourced_from_compiler; 460314564Sdim } 461254721Semaste 462314564Sdim // Was this UnwindPlan emitted by a compiler? 463314564Sdim void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler) { 464314564Sdim m_plan_is_sourced_from_compiler = from_compiler; 465314564Sdim } 466254721Semaste 467314564Sdim // Is this UnwindPlan valid at all instructions? If not, then it is assumed 468341825Sdim // valid at call sites, e.g. for exception handling. 469314564Sdim lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const { 470314564Sdim return m_plan_is_valid_at_all_instruction_locations; 471314564Sdim } 472254721Semaste 473314564Sdim // Is this UnwindPlan valid at all instructions? If not, then it is assumed 474341825Sdim // valid at call sites, e.g. for exception handling. 475314564Sdim void SetUnwindPlanValidAtAllInstructions( 476314564Sdim lldb_private::LazyBool valid_at_all_insn) { 477314564Sdim m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn; 478314564Sdim } 479254721Semaste 480360784Sdim // Is this UnwindPlan for a signal trap frame? If so, then its saved pc 481360784Sdim // may have been set manually by the signal dispatch code and therefore 482360784Sdim // not follow a call to the child frame. 483360784Sdim lldb_private::LazyBool GetUnwindPlanForSignalTrap() const { 484360784Sdim return m_plan_is_for_signal_trap; 485360784Sdim } 486360784Sdim 487360784Sdim void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap) { 488360784Sdim m_plan_is_for_signal_trap = is_for_signal_trap; 489360784Sdim } 490360784Sdim 491314564Sdim int GetRowCount() const; 492254721Semaste 493314564Sdim void Clear() { 494314564Sdim m_row_list.clear(); 495314564Sdim m_plan_valid_address_range.Clear(); 496314564Sdim m_register_kind = lldb::eRegisterKindDWARF; 497314564Sdim m_source_name.Clear(); 498314564Sdim m_plan_is_sourced_from_compiler = eLazyBoolCalculate; 499314564Sdim m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate; 500360784Sdim m_plan_is_for_signal_trap = eLazyBoolCalculate; 501314564Sdim m_lsda_address.Clear(); 502314564Sdim m_personality_func_addr.Clear(); 503314564Sdim } 504280031Sdim 505314564Sdim const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const; 506280031Sdim 507314564Sdim Address GetLSDAAddress() const { return m_lsda_address; } 508280031Sdim 509314564Sdim void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; } 510280031Sdim 511314564Sdim Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; } 512314564Sdim 513314564Sdim void SetPersonalityFunctionPtr(Address presonality_func_ptr) { 514314564Sdim m_personality_func_addr = presonality_func_ptr; 515314564Sdim } 516314564Sdim 517254721Semasteprivate: 518314564Sdim typedef std::vector<RowSP> collection; 519314564Sdim collection m_row_list; 520314564Sdim AddressRange m_plan_valid_address_range; 521314564Sdim lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers 522314564Sdim // are in terms of - will need to be 523314564Sdim // translated to lldb native reg nums at unwind time 524314564Sdim uint32_t m_return_addr_register; // The register that has the return address 525314564Sdim // for the caller frame 526314564Sdim // e.g. the lr on arm 527314564Sdim lldb_private::ConstString 528314564Sdim m_source_name; // for logging, where this UnwindPlan originated from 529314564Sdim lldb_private::LazyBool m_plan_is_sourced_from_compiler; 530314564Sdim lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; 531360784Sdim lldb_private::LazyBool m_plan_is_for_signal_trap; 532280031Sdim 533314564Sdim Address m_lsda_address; // Where the language specific data area exists in the 534314564Sdim // module - used 535314564Sdim // in exception handling. 536314564Sdim Address m_personality_func_addr; // The address of a pointer to the 537314564Sdim // personality function - used in 538314564Sdim // exception handling. 539314564Sdim}; // class UnwindPlan 540254721Semaste 541254721Semaste} // namespace lldb_private 542254721Semaste 543296417Sdim#endif // liblldb_UnwindPlan_h 544